Skip to content

Float once-used let binding into a recursive function

Consider this code

  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

  let go 10 = let x = f x0
              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.

Trac metadata
Trac field Value
Version 7.10.2
Type Task
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
Edited by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information