Note [No unboxed tuple for single, unlifted transit var]
When there's only a single, unlifted transit var (Note [Worker/wrapper for CPR]), we don't wrap an unboxed singleton tuple around it (which otherwise would be needed to suspend evaluation) and return the unlifted thing directly. E.g. ``` f :: Int -> Int f x = x+1 ``` We certainly want `$wf :: Int# -> Int#`, not `$wf :: Int# -> (# Int# #)`. This is OK as long as we know that evaluation of the returned thing terminates quickly, as is the case for fields of unlifted type like `Int#`. But more generally, this should also be true for *lifted* types that terminate quickly! Consider from `T18109`: ``` data F = F (Int -> Int) f :: Int -> F f n = F (+n) data T = T (Int, Int) g :: T -> T g t@(T p) = p `seq` t data U = U ![Int] h :: Int -> U h n = U [0..n] ``` All of the nested fields are actually ok-for-speculation and thus OK to return unboxed instead of in an unboxed singleton tuple: 1. The field of `F` is a HNF. We want `$wf :: Int -> Int -> Int`. We get `$wf :: Int -> (# Int -> Int #)`. 2. The field of `T` is `seq`'d in `g`. We want `$wg :: (Int, Int) -> (Int, Int)`. We get `$wg :: (Int, Int) -> (# (Int, Int) #)`. 3. The field of `U` is strict and thus always evaluated. We want `$wh :: Int# -> [Int]`. We'd get `$wh :: Int# -> (# [Int] #)`. By considering vars as unlifted that satisfy 'exprIsHNF', we catch (3). Why not check for 'exprOkForSpeculation'? Quite perplexingly, evaluated vars are not ok-for-spec, see Note [exprOkForSpeculation and evaluated variables]. For (1) and (2) we would have to look at the term. WW only looks at the type and the CPR signature, so the only way to fix (1) and (2) would be to have a nested termination signature, like in MR !1866.
References 2
- Worker/wrapper for CPR GHC.Core.Opt.WorkWrap.Utils
- exprOkForSpeculation and evaluated variables GHC.Core.Utils
Referenced by 2
- GHC.Core.Opt.WorkWrap.Utils call site ×2