
#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