diff options
Diffstat (limited to 'testsuite/tests/cpranal/sigs/T19398.hs')
-rw-r--r-- | testsuite/tests/cpranal/sigs/T19398.hs | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/testsuite/tests/cpranal/sigs/T19398.hs b/testsuite/tests/cpranal/sigs/T19398.hs new file mode 100644 index 0000000000..e0347fd502 --- /dev/null +++ b/testsuite/tests/cpranal/sigs/T19398.hs @@ -0,0 +1,32 @@ +{-# LANGUAGE BangPatterns #-} + +module T19398 where + +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 + +-- | An interesting artifact is that the following function has the Nested CPR +-- property, and we could in theory exploit that: +g :: (Int, Int) -> (Int, Int) +g p@(!x, !y) | x == y = error "blah" +g p = p |