2 CmmLive, BlockEntryLiveness,
17 -----------------------------------------------------------------------------
18 -- Calculating what variables are live on entry to a basic block
19 -----------------------------------------------------------------------------
21 -- The variables live on entry to a block
22 type CmmLive = UniqSet LocalReg
24 -- A mapping from block labels to the variables live on entry
25 type BlockEntryLiveness = BlockEnv CmmLive
27 -----------------------------------------------------------------------------
28 -- cmmLiveness and helpers
29 -----------------------------------------------------------------------------
30 cmmLiveness :: [CmmBasicBlock] -> BlockEntryLiveness
32 fixedpoint (cmmBlockDependants sources)
33 (cmmBlockUpdate blocks')
35 (listToUFM [(blockId b, emptyUniqSet) | b <- blocks])
37 sources = cmmBlockSources blocks
38 blocks' = cmmBlockNames blocks
41 -- For debugging, annotate each block with a comment indicating
42 -- the calculated live variables
44 BlockEnv (UniqSet LocalReg) -> CmmBasicBlock -> CmmBasicBlock
45 cmmLivenessComment live (BasicBlock ident stmts) =
46 BasicBlock ident stmts' where
47 stmts' = (CmmComment $ mkFastString $ showSDoc $ ppr $ live'):stmts
48 live' = map CmmLocal $ uniqSetToList $ lookupWithDefaultUFM live emptyUniqSet ident
52 --------------------------------
55 -- Calculates a table of blocks
56 -- that might need updating after
57 -- a given block is updated
58 --------------------------------
59 cmmBlockSources :: [CmmBasicBlock] -> BlockEnv (UniqSet BlockId)
60 cmmBlockSources blocks = foldr aux emptyUFM blocks
63 -> BlockEnv (UniqSet BlockId)
64 -> BlockEnv (UniqSet BlockId)
65 aux block sourcesUFM =
66 foldUniqSet (add_source_edges $ blockId block)
68 (branch_targets $ blockStmts block)
70 add_source_edges :: BlockId -> BlockId
71 -> BlockEnv (UniqSet BlockId)
72 -> BlockEnv (UniqSet BlockId)
73 add_source_edges source target ufm =
74 addToUFM_Acc (flip addOneToUniqSet) unitUniqSet ufm target source
76 branch_targets :: [CmmStmt] -> UniqSet BlockId
77 branch_targets stmts =
78 mkUniqSet $ concatMap target stmts where
79 target (CmmBranch ident) = [ident]
80 target (CmmCondBranch _ ident) = [ident]
81 target (CmmSwitch _ blocks) = mapMaybe id blocks
84 --------------------------------
87 -- Calculates a table that maps
88 -- block names to the list
89 -- of statements inside them
90 --------------------------------
91 cmmBlockNames :: [CmmBasicBlock] -> BlockEnv [CmmStmt]
92 cmmBlockNames blocks = listToUFM $ map block_name blocks where
93 block_name b = (blockId b, blockStmts b)
95 --------------------------------
98 -- Given the table calculated
99 -- by cmmBlockSources created,
100 -- list all blocks that depend
101 -- on the result of a particular
103 --------------------------------
104 cmmBlockDependants :: BlockEnv (UniqSet BlockId) -> BlockId -> [BlockId]
105 cmmBlockDependants sources ident =
106 uniqSetToList $ lookupWithDefaultUFM sources emptyUniqSet ident
108 --------------------------------
111 -- Given the table from
112 -- cmmBlockNames and a block
113 -- that was updated, calculate
114 -- an updated BlockEntryLiveness
115 --------------------------------
120 -> BlockEntryLiveness
121 -> Maybe BlockEntryLiveness
122 cmmBlockUpdate blocks node _ state =
123 if (sizeUniqSet old_live) == (sizeUniqSet new_live)
125 else Just $ addToUFM state node new_live
127 new_live = cmmStmtListLive state block
128 old_live = lookupWithDefaultUFM state missing_live node
129 block = lookupWithDefaultUFM blocks missing_block node
130 missing_live = panic "unknown block id during liveness analysis"
131 missing_block = panic "unknown block id during liveness analysis"
133 -----------------------------------------------------------------------------
134 -- CmmBlockLive, cmmStmtListLive and helpers
135 -----------------------------------------------------------------------------
137 -- Calculate the live registers for a local block (list of statements)
139 cmmStmtListLive :: BlockEntryLiveness -> [CmmStmt] -> CmmLive
140 cmmStmtListLive other_live stmts =
141 foldr ((.) . (cmmStmtLive other_live)) id stmts emptyUniqSet
143 -----------------------------------------------------------------------------
144 -- This code is written in the style of a state monad,
145 -- but since Control.Monad.State is not in the core
146 -- we can't use it in GHC, so we'll fake one here.
147 -- We don't need a return value so well leave it out.
148 -- Thus 'bind' reduces to function composition.
150 type CmmLivenessTransformer = CmmLive -> CmmLive
152 -- Helpers for the "Monad"
153 addLive, addKilled :: CmmLive -> CmmLivenessTransformer
154 addLive new_live live = live `unionUniqSets` new_live
155 addKilled new_killed live = live `minusUniqSet` new_killed
157 --------------------------------
158 -- Liveness of a CmmStmt
159 --------------------------------
160 cmmFormalsToLiveLocals :: CmmFormals -> [LocalReg]
161 cmmFormalsToLiveLocals [] = []
162 cmmFormalsToLiveLocals ((CmmGlobal _,_):args) = cmmFormalsToLiveLocals args
163 cmmFormalsToLiveLocals ((CmmLocal r,_):args) = r:cmmFormalsToLiveLocals args
165 cmmStmtLive :: BlockEntryLiveness -> CmmStmt -> CmmLivenessTransformer
166 cmmStmtLive _ (CmmNop) = id
167 cmmStmtLive _ (CmmComment _) = id
168 cmmStmtLive _ (CmmAssign reg expr) =
169 cmmExprLive expr . reg_liveness where
172 (CmmLocal reg') -> addKilled $ unitUniqSet reg'
174 cmmStmtLive _ (CmmStore expr1 expr2) =
175 cmmExprLive expr2 . cmmExprLive expr1
176 cmmStmtLive _ (CmmCall target results arguments _) =
178 foldr ((.) . cmmExprLive) id (map fst arguments) .
179 addKilled (mkUniqSet $ cmmFormalsToLiveLocals results) where
182 (CmmForeignCall target _) -> cmmExprLive target
184 cmmStmtLive other_live (CmmBranch target) =
185 addLive (lookupWithDefaultUFM other_live emptyUniqSet target)
186 cmmStmtLive other_live (CmmCondBranch expr target) =
188 addLive (lookupWithDefaultUFM other_live emptyUniqSet target)
189 cmmStmtLive other_live (CmmSwitch expr targets) =
191 (foldr ((.) . (addLive .
192 lookupWithDefaultUFM other_live emptyUniqSet))
194 (mapCatMaybes id targets))
195 cmmStmtLive _ (CmmJump expr params) =
196 const (cmmExprLive expr $ foldr ((.) . cmmExprLive) id (map fst params) $ emptyUniqSet)
197 cmmStmtLive _ (CmmReturn params) =
198 const (foldr ((.) . cmmExprLive) id (map fst params) $ emptyUniqSet)
200 --------------------------------
201 -- Liveness of a CmmExpr
202 --------------------------------
203 cmmExprLive :: CmmExpr -> CmmLivenessTransformer
204 cmmExprLive expr = addLive (mkUniqSet $ expr_liveness expr) where
205 expr_liveness :: CmmExpr -> [LocalReg]
206 expr_liveness (CmmLit _) = []
207 expr_liveness (CmmLoad expr _) = expr_liveness expr
208 expr_liveness (CmmReg reg) = reg_liveness reg
209 expr_liveness (CmmMachOp _ exprs) = concatMap expr_liveness exprs
210 expr_liveness (CmmRegOff reg _) = reg_liveness reg
212 reg_liveness :: CmmReg -> [LocalReg]
213 reg_liveness (CmmLocal reg) = [reg]
214 reg_liveness (CmmGlobal _) = []