Note [Binder swap]
The "binder swap" transformation swaps occurrence of the
scrutinee of a case for occurrences of the case-binder:
(1) case x of b { pi -> ri }
==>
case x of b { pi -> ri[b/x] }
(2) case (x |> co) of b { pi -> ri }
==>
case (x |> co) of b { pi -> ri[b |> sym co/x] }
The substitution ri[b/x] etc is done by the occurrence analyser.
See Note [The binder-swap substitution].
There are two reasons for making this swap:
(A) It reduces the number of occurrences of the scrutinee, x.
That in turn might reduce its occurrences to one, so we
can inline it and save an allocation. E.g.
let x = factorial y in case x of b { I# v -> ...x... }
If we replace 'x' by 'b' in the alternative we get
let x = factorial y in case x of b { I# v -> ...b... }
and now we can inline 'x', thus
case (factorial y) of b { I# v -> ...b... }
(B) The case-binder b has unfolding information; in the
example above we know that b = I# v. That in turn allows
nested cases to simplify. Consider
case x of b { I# v ->
...(case x of b2 { I# v2 -> rhs })...
If we replace 'x' by 'b' in the alternative we get
case x of b { I# v ->
...(case b of b2 { I# v2 -> rhs })...
and now it is trivial to simplify the inner case:
case x of b { I# v ->
...(let b2 = b in rhs)...
The same can happen even if the scrutinee is a variable
with a cast: see Note [Case of cast]
The reason for doing these transformations /here in the occurrence
analyser/ is because it allows us to adjust the OccInfo for 'x' and
'b' as we go.
* Suppose the only occurrences of 'x' are the scrutinee and in the
ri; then this transformation makes it occur just once, and hence
get inlined right away.
* If instead the Simplifier replaces occurrences of x with
occurrences of b, that will mess up b's occurrence info. That in
turn might have consequences.
There is a danger though. Consider
let v = x +# y
in case (f v) of w -> ...v...v...
And suppose that (f v) expands to just v. Then we'd like to
use 'w' instead of 'v' in the alternative. But it may be too
late; we may have substituted the (cheap) x+#y for v in the
same simplifier pass that reduced (f v) to v.
I think this is just too bad. CSE will recover some of it. References 2
- Case of cast GHC.Core.Opt.OccurAnal
- The binder-swap substitution GHC.Core.Opt.OccurAnal
Referenced by 5
- GHC.Core.Opt.OccurAnal call site
- Case of cast GHC.Core.Opt.OccurAnal
- Occurrence analysis for join points GHC.Core.Opt.OccurAnal
- GHC.Core.Opt.Simplify.Iteration call site
- Add unfolding for scrutinee GHC.Core.Opt.Simplify.Iteration