
#14827: Recognize when inlining would create a join point -------------------------------------+------------------------------------- Reporter: ersetzen | Owner: (none) Type: feature | Status: new request | Priority: normal | Milestone: Component: Compiler | Version: 8.2.2 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: -------------------------------------+------------------------------------- [https://www.reddit.com/r/haskell/comments/7yh8ar/i_wrote_a_program_that_runs... 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] -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14827 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler