Implement unboxed sum primitive type
[ghc.git] / compiler / cmm / CmmLive.hs
1 {-# LANGUAGE BangPatterns #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE GADTs #-}
4 {-# LANGUAGE ScopedTypeVariables #-}
5
6 -- See Note [Deprecations in Hoopl] in Hoopl module
7 {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
8
9 module CmmLive
10 ( CmmLocalLive
11 , cmmLocalLiveness
12 , cmmGlobalLiveness
13 , liveLattice
14 , gen, kill, gen_kill
15 )
16 where
17
18 import DynFlags
19 import BlockId
20 import Cmm
21 import CmmUtils
22 import PprCmmExpr ()
23
24 import Hoopl
25 import Maybes
26 import Outputable
27
28 -----------------------------------------------------------------------------
29 -- Calculating what variables are live on entry to a basic block
30 -----------------------------------------------------------------------------
31
32 -- | The variables live on entry to a block
33 type CmmLive r = RegSet r
34 type CmmLocalLive = CmmLive LocalReg
35
36 -- | The dataflow lattice
37 liveLattice :: Ord r => DataflowLattice (CmmLive r)
38 {-# SPECIALIZE liveLattice :: DataflowLattice (CmmLive LocalReg) #-}
39 {-# SPECIALIZE liveLattice :: DataflowLattice (CmmLive GlobalReg) #-}
40 liveLattice = DataflowLattice "live LocalReg's" emptyRegSet add
41 where add _ (OldFact old) (NewFact new) =
42 (changeIf $ sizeRegSet join > sizeRegSet old, join)
43 where !join = plusRegSet old new
44
45
46 -- | A mapping from block labels to the variables live on entry
47 type BlockEntryLiveness r = BlockEnv (CmmLive r)
48
49 -----------------------------------------------------------------------------
50 -- | Calculated liveness info for a CmmGraph
51 -----------------------------------------------------------------------------
52
53 cmmLocalLiveness :: DynFlags -> CmmGraph -> BlockEntryLiveness LocalReg
54 cmmLocalLiveness dflags graph =
55 check $ dataflowAnalBwd graph [] $ analBwd liveLattice (xferLive dflags)
56 where entry = g_entry graph
57 check facts = noLiveOnEntry entry
58 (expectJust "check" $ mapLookup entry facts) facts
59
60 cmmGlobalLiveness :: DynFlags -> CmmGraph -> BlockEntryLiveness GlobalReg
61 cmmGlobalLiveness dflags graph =
62 dataflowAnalBwd graph [] $ analBwd liveLattice (xferLive dflags)
63
64 -- | On entry to the procedure, there had better not be any LocalReg's live-in.
65 noLiveOnEntry :: BlockId -> CmmLive LocalReg -> a -> a
66 noLiveOnEntry bid in_fact x =
67 if nullRegSet in_fact then x
68 else pprPanic "LocalReg's live-in to graph" (ppr bid <+> ppr in_fact)
69
70 -- | The transfer equations use the traditional 'gen' and 'kill'
71 -- notations, which should be familiar from the Dragon Book.
72 gen :: UserOfRegs r a => DynFlags -> a -> RegSet r -> RegSet r
73 {-# INLINE gen #-}
74 gen dflags a live = foldRegsUsed dflags extendRegSet live a
75
76 kill :: DefinerOfRegs r a => DynFlags -> a -> RegSet r -> RegSet r
77 {-# INLINE kill #-}
78 kill dflags a live = foldRegsDefd dflags deleteFromRegSet live a
79
80 gen_kill :: (DefinerOfRegs r a, UserOfRegs r a)
81 => DynFlags -> a -> CmmLive r -> CmmLive r
82 {-# INLINE gen_kill #-}
83 gen_kill dflags a = gen dflags a . kill dflags a
84
85 -- | The transfer function
86 xferLive :: forall r . ( UserOfRegs r (CmmNode O O)
87 , DefinerOfRegs r (CmmNode O O)
88 , UserOfRegs r (CmmNode O C)
89 , DefinerOfRegs r (CmmNode O C))
90 => DynFlags -> BwdTransfer CmmNode (CmmLive r)
91 {-# SPECIALIZE xferLive :: DynFlags -> BwdTransfer CmmNode (CmmLive LocalReg) #-}
92 {-# SPECIALIZE xferLive :: DynFlags -> BwdTransfer CmmNode (CmmLive GlobalReg) #-}
93 xferLive dflags = mkBTransfer3 fst mid lst
94 where fst _ f = f
95 mid :: CmmNode O O -> CmmLive r -> CmmLive r
96 mid n f = gen_kill dflags n f
97 lst :: CmmNode O C -> FactBase (CmmLive r) -> CmmLive r
98 lst n f = gen_kill dflags n $ joinOutFacts liveLattice n f