
#10918: Float once-used let binding into a recursive function -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | -------------------------------------+------------------------------------- Consider this code {{{#!hs let x = f x0 in let go 10 = x go i = go (i+1) in go (0::Int) }}} Currently, this is pretty much the core that comes out at the end. But what we want to see instead is {{{#!hs let go 10 = let x = f x 0 in x go i = go (i+1) in go (0::Int) }}} In general, we do not want to float a binding into a recursive function, because we would risk doing the allocation and/or evaluation of it multiple times. But in this case, we can see that it is going to be used at most once, so it is safe to do so. Even more: In the slightly less contrived examples that I was looking at, the call to `x` was happening in the a less likely code path, so this way we’d avoid doing the allocation in most cases, a clear win. It might be enough to simply make `CallArity` (or rather the cardinality analysis done by call arity) tell the rest of the compiler that it found that `x` is called at most once, and hopefully the simplifier knows what to make of that information. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10918 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler