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 #-}
|