summaryrefslogtreecommitdiff
path: root/testsuite/tests/cpranal/sigs/T19398.hs
blob: e0347fd502ab543d1ac927e3c67ee94b449d6aa7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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