Note [Floating single-alternative cases]
Consider this:
data T a = MkT !a
f :: T Int -> blah
f x vs = case x of { MkT y ->
let f vs = ...(case y of I# w -> e)...f..
in f vs
Here we can float the (case y ...) out, because y is sure
to be evaluated, to give
f x vs = case x of { MkT y ->
case y of I# w ->
let f vs = ...(e)...f..
in f vs
That saves unboxing it every time round the loop. It's important in
some DPH stuff where we really want to avoid that repeated unboxing in
the inner loop.
Things to note:
* The test we perform is exprIsHNF, and /not/ exprOkForSpeculation.
- exprIsHNF catches the key case of an evaluated variable
- exprOkForSpeculation is /false/ of an evaluated variable;
See Note [exprOkForSpeculation and evaluated variables] in GHC.Core.Utils
So we'd actually miss the key case!
- Nothing is gained from the extra generality of exprOkForSpeculation
since we only consider floating a case whose single alternative
is a DataAlt K a b -> rhs
* We can't float a case to top level
* It's worth doing this float even if we don't float
the case outside a value lambda. Example
case x of {
MkT y -> (case y of I# w2 -> ..., case y of I# w2 -> ...)
If we floated the cases out we could eliminate one of them.
* We only do this with a single-alternative case References 1
- exprOkForSpeculation and evaluated variables GHC.Core.Utils
Referenced by 4
- GHC.Core.Make call site
- GHC.Core.Opt.SetLevels call site
- Check the output scrutinee for exprIsHNF GHC.Core.Opt.SetLevels
- exprOkForSpeculation: case expressions GHC.Core.Utils