[GHC] #14137: Do more inlining into non-recursive join points

GHC ghc-devs at haskell.org
Wed Aug 23 23:13:25 UTC 2017


#14137: Do more inlining into non-recursive join points
-------------------------------------+-------------------------------------
        Reporter:  simonpj           |                Owner:  nomeata
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.2.1
      Resolution:                    |             Keywords:  JoinPoints
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 > That’s what I feel that a call to a join point outside of letrec would
 be more explicit

 Yes but it doesn't work in general.  What if it was
 {{{
 let ys = expensive in
 letrec f xs = case xs of
                []     -> ys : []
                (p:ps) -> p : f ps
 in f ps : qs
 }}}
 Then `ys` is not a join point in any shape or form; but all the argument
 about being able to inline it is equally valid.  I don't want to build a
 complicated infrastructure that only solves part of the problem!

 Ah, silly me.  I was struck with a brilliant idea, and then realised that
 it's exactly what you describe in comment:12.  Take any case alternative
 in the recursive function that does not mention the recursive function,
 and make it into a non-recursive join point, thus:
 {{{
 letrec f xs = case xs of
                 [p]    -> e1   -- no f's
                 (p:ps) -> e2[f]

 ===>

 let f as = join j p = e1 in
            joinrec f x = case xs of
                 [p] -> j p
                 (p:ps) -> e2[f]
            in f as
 }}}
 Now we can readily inline ys into e1 if `f` if called once (and hence the
 `\as` is marked one-shot.  Moreover, it works for arbitary expressions e1.

 Of course you worked this out already a few days ago; I just didn't read
 carefully enough.  Sorry.  I acrually rather like it now, as a part of the
 loopification transformation.

 Still to think about

 * A remaining tricky point is that we need to stop one of these carefully-
 constructed non-recursive join points being inlined into a recursive join
 point, even if it is invoked at just one place.  That should not be hard.
 And in a final run of the simplifer (or in CorePrep) we could switch off
 that restriction and let it inline.

 Go for it!  (But do these other simpler things first.)

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14137#comment:17>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list