Account for evaluatedness of scrutinees in `sizeExpr`
The motivation for !12239 boils down to the following. Consider the following functions:
f1 xs = case xs of xs' { __DEFAULT ->
let t = blah xs'
in
case xs' of {
[] -> (t, True)
_:_ -> (t, False)
}}
f2 xs =
let t = blah xs
in
case xs of {
[] -> (t, True)
_:_ -> (t, False)
}
These two functions are semantically equivalent. It might appear that f1 is larger than f2, since the former has one extra case statement, but in fact due to tag inference the two functions will generate nearly the same amount of code: In f1 the outer case xs will perform an eval and the inner case xs' will perform a branch but no eval, while in f2 the case xs will perform both an eval and a branch. (f2 will probably actually generate slightly more code because it has to store an extra free variable t across the call to xs.)
But this subtlety is lost on sizeExpr, which ultimately drives our inlining decisions. We should improve sizeExpr so that the f1 form of this function is no less likely to inline than the f2 form.
(!12239 proposes to rewrite f1 into f2 in the hopes of slightly better inlining, even though f2 is arguably just plain worse: If t is ever entered, xs will certainly already have been evaluated but blah may only get a pointer to the location of the original thunk (now containing an IND if GC hasn't run yet) rather a pointer to the properly evaluated result xs' of evaluating xs.)