Optimistic field binder CPR is a huge hack
In !4976 (closed), which was about fixing #19232 (closed) (getting rid of opimistic case binder CPR), we got hung up about the many ways in which the severely underdocumented optimistic field binder CPR is unsound (in the sense that it causes reboxing) and how to fix it.
I propose to do so via a light version of Nested CPR (#18174 (closed)) that builds on Note [CPR for binders that will be unboxed]
to give deeply unboxed parameters a nested CPR property. No termination analysis necessary here, because strict binders terminate anyway. It will all stay within GHC.Types.Cpr
.
Here's a regression test that shows how Optimistic field binder CPR causes reboxing:
data T a = MkT !a !a
f :: T a -> T a
f (MkT a b) = MkT b a
{-# NOINLINE f #-}
-- | Should *not* have the CPR property, even though the scrutinee is a
-- variable with the CPR property. It shows how Test (A) of
-- Historical Note [Optimistic field binder CPR] is unsound.
a :: Int -> Int
a n
| n == 0 = n
| even n = case q of MkT x y -> if x == y then x else y
| otherwise = case q of MkT x y -> if x == y then y else x
where
q = f $ f $ f $ f $ f $ f $ f $ MkT n n
-- | Should not have the CPR property, because 'x' will not be unboxed.
-- It shows how Test (C) of Historical Note [Optimistic field binder CPR] is
-- unsound.
c :: (Int, Int) -> Int
c (x,_) = x