[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