[GHC] #14827: Recognize when inlining would create a join point

GHC ghc-devs at haskell.org
Mon Feb 19 23:16:26 UTC 2018


#14827: Recognize when inlining would create a join point
-------------------------------------+-------------------------------------
        Reporter:  ersetzen          |                Owner:  (none)
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.2.2
      Resolution:                    |             Keywords:  JoinPoints
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Runtime           |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Description changed by ersetzen:

Old description:

> [https://www.reddit.com/r/haskell/comments/7yh8ar/i_wrote_a_program_that_runs_about_10_times_faster/
> This discussion] revolved around a program that runs 10x faster under
> ghci.
>
> One way to solve this is to remove a superfluous inline pragma which
> allows the following transformation to happen:
>
> {{{
> letrec {
> f a = case e of {
>     p1 -> f a';
>     p2 -> (# l, r #);
> }} in case f e2 of { (# l, r #) -> e3; }
> }}}
>
> into
>
> {{{
> joinrec {
> f a = case e of {
>     p1 -> jump f a';
>     p2 -> e3;
> }} in jump f e2
> }}}
>
> More generally a recursive let binding that is called exactly once from
> the outside. If all recursive calls are tail calls and the outside one
> isn't then we could safely replace the call with the binding and end up
> with join points. In this case it means a 10x speedup so it might be
> worth doing generally.
>

> {{{
> letrec { fi = ei; } in ... (fj e) ... => ... (joinrec { fi = ei; } in fj
> e) ...
> }}}
>
> [https://gist.github.com/AndreasPK/8e6f0cbf253f0930f4cda81e685ac136  Self
> contained example]

New description:

 [https://www.reddit.com/r/haskell/comments/7yh8ar/i_wrote_a_program_that_runs_about_10_times_faster/
 This discussion] revolved around a program that runs 10x faster under
 ghci.

 One way to solve this is to remove a superfluous inline pragma which
 allows the following transformation to happen:

 {{{
 letrec {
 f a = case e of {
     p1 -> f a';
     p2 -> (# l, r #);
 }} in case f e2 of { (# l, r #) -> e3; }
 }}}

 into

 {{{
 joinrec {
 f a = case e of {
     p1 -> jump f a';
     p2 -> e3;
 }} in jump f e2
 }}}

 More generally a recursive let binding that is called exactly once from
 the outside. If all recursive calls are tail calls and the outside one
 isn't then we could safely replace the call with the binding and end up
 with join points. In this case it means a 10x speedup so it might be worth
 doing generally.


 {{{
 letrec { fi = ei; } in ... (fj e) ... => ... (joinrec { fi = ei; } in jump
 fj e) ...
 }}}

 [https://gist.github.com/AndreasPK/8e6f0cbf253f0930f4cda81e685ac136  Self
 contained example]

--

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


More information about the ghc-tickets mailing list