summaryrefslogtreecommitdiff
path: root/testsuite/tests/stranal/sigs/T19871.hs
blob: 564a055df475a107c46f9417f99e9b2e4f14c2d7 (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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
{-# OPTIONS_GHC -O2 -fforce-recomp #-}

-- | From Note [Boxity Analysis] and related Notes
module T19871 where

data Huge
  = Huge
  { f1 :: Bool
  , f2 :: Bool
  , f3 :: Bool
  , f4 :: Bool
  , f5 :: Bool
  , f6 :: Bool
  , f7 :: Bool
  , f8 :: Bool
  , f9 :: Bool
  , f10 :: Bool
  , f11 :: Bool
  , f12 :: Bool }

-- | Should not unbox Huge
ann :: Huge -> (Bool, Huge)
ann h@(Huge{f1=True}) = (False, h)
ann h                 = (True,  h)
{-# NOINLINE ann #-}

-- A few examples demonstrating the lubBoxity = unboxedWins tradeoff

-- | Should unbox 'z'.
-- We won't with `lubBoxity = boxedWins`.
-- We will  with `lubBoxity = unboxedWins`.
sumIO :: Int -> Int -> IO Int
sumIO 0 !z = return z
sumIO n !z = sumIO (n-1) (z+n)
{-# NOINLINE sumIO #-}

-- | Should /not/ unbox 'h'.
-- We won't with `lubBoxity = boxedWins`.
-- We will  with `lubBoxity = unboxedWins`.
update :: Huge -> (Bool, Huge)
update h@(Huge{f1=True}) = (False, h{f1=False})
update h                 = (True,  h)
{-# NOINLINE update #-}

-- | Should /not/ unbox 'h'.
-- We won't with `lubBoxity = boxedWins`.
-- We will  with `lubBoxity = unboxedWins`.
guarded :: (Huge -> Bool) -> Huge -> Bool
guarded g h | f1 h      = True
            | otherwise = g h
{-# NOINLINE guarded #-}

-- | Should /not/ unbox 'h'.
-- We won't with `lubBoxity = boxedWins`.
-- We will  with `lubBoxity = unboxedWins`.
--
-- This example also demonstrates the usefulness of carrying a Boxity in Poly.
-- Most absent sub-demands here should be considered Boxed (and of course we
-- also need Unboxed absent Poly). See Note [Boxity in Poly].
absent :: Huge -> Int
absent h = if f1 h || f2 h then g h else 2
  where
    g :: a -> Int
    g a = a `seq` f a True
    {-# NOINLINE g #-}
    f :: a -> Bool -> Int
    f _ True = 1
    f a False = a `seq` 2
    {-# NOINLINE f #-}
{-# NOINLINE absent #-}