Note [Pin evaluatedness on floats]
When creating a new float `sat=e` in `mkNonRecFloat`, we propagate `sat` with an `evaldUnfolding` if `e` is a value. To see why, consider a call to a CBV function, such as a DataCon worker with *strict* fields, in an argument context, such as data Box a = Box !a ... f (Box e) ... where `f` is *lazy* and `e` is ok-for-spec, e.g. `e = I# (x +# 1#)`. After ANFisation, we want to get the very nice code case x +# 1# of x' -> let sat = I# x' in let sat2 = Box sat in f sat2 Note that Case (2) of Note [wantFloatLocal] is in effect. That is, * x' is unlifted but ok-for-spec, hence floated out of the lazy arg of f * Since x' is unlifted, `I# x'` is a value, and so `sat` can be let-bound. * Since `sat` is a value, `Box sat` is a value as well, and so `sat2` can be let-bound. Hence no thunk needs to be allocated! However, in order to recognise `Box sat` as a value, it is crucial that the newly created `sat` has an `evaldUnfolding`; otherwise the strict worker `Box` forces an eval on `sat`. and we would get the far worse code let sat2 = case x +# 1# of x' -> case I# x' of sat' -> Box sat in f sat2 A live example of this is T24730, inspired by $walexGetByte.
References 1
- wantFloatLocal GHC.CoreToStg.Prep
Referenced by 1
- GHC.CoreToStg.Prep call site