Excessive floating
Consider this program
foo = case error "wombat" of { True -> "fred"; False -> "bill" }
Currently, FloatOut will float that (error "wombat")
to top level, thus
lvl = error "wombat"
foo = case lvl of { True -> "fred"; False -> "bill" }
But that's a stupid thing to do. Nothing is gained.
The culprit is this code in GHC.Core.Opt.SetLevels
-- See Note [Floating to the top]
saves_alloc = isTopLvl dest_lvl
&& floatConsts env
&& (not strict_ctxt || is_bot || exprIsHNF expr)
For is_bot
expressions we always float. I think it should be (is_bot && escapes_value_lam)
. The main reason for floating is to make the function smaller, and more likely to inline; that's irrelevant for thunks.
Not a big deal, but easy to fix. I tripped over it when seeing this code in the output of SetLevels
for this example program
let {
<exit_s1oS,F<0,0>>
<exit_s1oS,F<0,0>>
= case let {
<lvl_s1oQ,F<0,0>>
<lvl_s1oQ,F<0,0>>
= Data.Text.Internal.Fusion.Common.head_empty
@GHC.Types.Char
($dIP1_s1oi
`cast` (Sym (GHC.Classes.N:IP[0]
<"callStack">_N <GHC.Stack.Types.CallStack>_N)
:: GHC.Stack.Types.CallStack
~R# (?callStack::GHC.Stack.Types.CallStack))) } in
lvl_s1oQ
of <wild_00,<0,2>> {
} } in
Notice that exit_s1oS
is going to top level, but (separately and uselessly) so is lvl_s1oQ
.