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 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.