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

GHC ghc-devs at haskell.org
Mon Aug 21 12:41: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):

 There are three threads here (maybe we need separate tickets):

 * '''The original ticket description''': this remains valid.  Did you try
 it?  It may not affect the `queens` example because of the other
 occurrences of `ds5` which I'd missed; but it's a valid and beneficial
 change regardless.

 * '''preInlineUnconditionally for join points''' (comment:7).  This ok,
 but it really should not make much difference in either direction.  Unlike
 most inlining, it doesn't eliminate an allocation; it only eliminates an
 unconditional jump; and that jump will probably be eliminated in Cmm
 anyway.  Doing the inlining cannot (I think) give rise to any knock-on
 optimisations.

   I'm intrigued why `scs` goes faster (comment:13).  Was that runtime or
 allocation?  Also in the `parsing001` benchmark, try with `-dshow-passes`
 to see if there's a change in the volume of generated code.  That's wha
 usually makes compiler perf change.

 * '''Floating out more join points'''.   I'm intrigued by your suggestion
 in comment:10, but I am not persuaded.
   * Generally speaking GHC inlines things that are called once, the exact
 reverse of ANF.  Doing is more direct and reduces clutter.
   * We'd need a way to ''stop'' these used-once join points being inlined.
   * Core has an operational interpretation, and introducing a join
 connotes an extra jump.  Maybe Cmm will eliminate it, but still.
   * Join points with parameters pass the parameters according to the
 calling convention, which we don't need.
   * Join points with parameters might be strictness analysed, specialised,
 and worker/wrappered.  All stupid for called-once join points.
   * Lastly, it doesn't solve the problem in general.  For example
 {{{
 let ys = expensive in
 letrec f xs = case xs of
                []     -> ys
                (p:ps) -> p : f ps
 in ...
 }}}
     Even after loopification `f` is not a `joinrec`.  But, if (and only
 if!) `f` is called once in `...`, it's  safe to inline `ys` in the RHS of
 `f`.  Dually, if it was
 {{{
 letrec f xs = case xs of
                []     -> expensive
                (p:ps) -> p : f ps
 in ...
 }}}
     (and `f` was called once "outside") we would not want to float
 `expensive` out.

   In short, this business of spotting the exit paths of a recursive loop
 is an interesting challenge, but it goes beyond join points.

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


More information about the ghc-tickets mailing list