Skip to content

WW for constructed products should not wrap an unboxed 1-tuple around evaluated binders/stuff that terminates rapidly

Consider

data T = T (Int, Int)

f :: T -> T
f t@(T p) = p `seq` t
{-# NOINLINE f #-}

For the better or the worse, we give f the CPR property (which is not up for discussion in this ticket) and WW to

$wf :: (Int, Int) -> (# (Int, Int) #)
$wf t = case t of t' { (x, y) -> (# t' #) }

f (T p) = case $wf p of { (# p' #) -> T p' }

The (# #) wrapping is unnecessary, since t' is already evaluated ("unlifted"). There alraedy is a special case in WorkWrap.Utils.mkWWcpr_help for the singleton, unlifted result type case, but it doesn't detect t' as unlifted, as operates purely by type. It appears that the function doesn't even have access to the expression it will wrap, and even if it had it's not easy to see how it could do the necessary analysis pre-simplication.

But with Nested CPR, we have the necessary termination info available! In particular, we would see that evaluation of t' terminates rapidly (it's a case binder) and would see so in the Cpr *c1(#) (note the #) for f. This enables mkWWcpr_help to safely drop the (# #) wrapping.

Edited by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information