5 cmmFormalsToLiveLocals,
8 #include "HsVersions.h"
18 -----------------------------------------------------------------------------
19 -- Calculating what variables are live on entry to a basic block
20 -----------------------------------------------------------------------------
22 -- | The variables live on entry to a block
23 type CmmLive = UniqSet LocalReg
25 -- | A mapping from block labels to the variables live on entry
26 type BlockEntryLiveness = BlockEnv CmmLive
28 -- | A mapping from block labels to the blocks that target it
29 type BlockSources = BlockEnv (UniqSet BlockId)
31 -- | A mapping from block labels to the statements in the block
32 type BlockStmts = BlockEnv [CmmStmt]
34 -----------------------------------------------------------------------------
35 -- | Calculated liveness info for a list of 'CmmBasicBlock'
36 -----------------------------------------------------------------------------
37 cmmLiveness :: [CmmBasicBlock] -> BlockEntryLiveness
39 fixedpoint (cmmBlockDependants sources)
40 (cmmBlockUpdate blocks')
42 (mkBlockEnv [(blockId b, emptyUniqSet) | b <- blocks])
44 sources :: BlockSources
45 sources = cmmBlockSources blocks
48 blocks' = mkBlockEnv $ map block_name blocks
50 block_name :: CmmBasicBlock -> (BlockId, [CmmStmt])
51 block_name b = (blockId b, blockStmts b)
54 -- For debugging, annotate each block with a comment indicating
55 -- the calculated live variables
57 BlockEnv (UniqSet LocalReg) -> CmmBasicBlock -> CmmBasicBlock
58 cmmLivenessComment live (BasicBlock ident stmts) =
59 BasicBlock ident stmts' where
60 stmts' = (CmmComment $ mkFastString $ showSDoc $ ppr $ live'):stmts
61 live' = map CmmLocal $ uniqSetToList $ lookupWithDefaultUFM live emptyUniqSet ident
65 -----------------------------------------------------------------------------
66 -- | Calculates a table of where one can lookup the blocks that might
67 -- need updating after a given block is updated in the liveness analysis
68 -----------------------------------------------------------------------------
69 cmmBlockSources :: [CmmBasicBlock] -> BlockSources
70 cmmBlockSources blocks = foldr aux emptyBlockEnv blocks
75 aux block sourcesUFM =
76 foldUniqSet (add_source_edges $ blockId block)
78 (branch_targets $ blockStmts block)
80 add_source_edges :: BlockId -> BlockId
83 add_source_edges source target ufm =
84 addToBEnv_Acc (flip addOneToUniqSet) unitUniqSet ufm target source
86 branch_targets :: [CmmStmt] -> UniqSet BlockId
87 branch_targets stmts =
88 mkUniqSet $ concatMap target stmts where
89 target (CmmBranch ident) = [ident]
90 target (CmmCondBranch _ ident) = [ident]
91 target (CmmSwitch _ blocks) = mapMaybe id blocks
94 -----------------------------------------------------------------------------
95 -- | Given the table calculated by 'cmmBlockSources', list all blocks
96 -- that depend on the result of a particular block.
98 -- Used by the call to 'fixedpoint'.
99 -----------------------------------------------------------------------------
100 cmmBlockDependants :: BlockSources -> BlockId -> [BlockId]
101 cmmBlockDependants sources ident =
102 uniqSetToList $ lookupWithDefaultBEnv sources emptyUniqSet ident
104 -----------------------------------------------------------------------------
105 -- | Given the table of type 'BlockStmts' and a block that was updated,
106 -- calculate an updated BlockEntryLiveness
107 -----------------------------------------------------------------------------
112 -> BlockEntryLiveness
113 -> Maybe BlockEntryLiveness
114 cmmBlockUpdate blocks node _ state =
115 if (sizeUniqSet old_live) == (sizeUniqSet new_live)
117 else Just $ extendBlockEnv state node new_live
119 new_live, old_live :: CmmLive
120 new_live = cmmStmtListLive state block_stmts
121 old_live = lookupWithDefaultBEnv state missing_live node
123 block_stmts :: [CmmStmt]
124 block_stmts = lookupWithDefaultBEnv blocks missing_block node
126 missing_live = panic "unknown block id during liveness analysis"
127 missing_block = panic "unknown block id during liveness analysis"
129 -----------------------------------------------------------------------------
131 -----------------------------------------------------------------------------
132 -----------------------------------------------------------------------------
133 -- CmmBlockLive, cmmStmtListLive and helpers
134 -----------------------------------------------------------------------------
136 -- Calculate the live registers for a local block (list of statements)
138 cmmStmtListLive :: BlockEntryLiveness -> [CmmStmt] -> CmmLive
139 cmmStmtListLive other_live stmts =
140 foldr ((.) . (cmmStmtLive other_live)) id stmts emptyUniqSet
142 -----------------------------------------------------------------------------
143 -- This code is written in the style of a state monad,
144 -- but since Control.Monad.State is not in the core
145 -- we can't use it in GHC, so we'll fake one here.
146 -- We don't need a return value so well leave it out.
147 -- Thus 'bind' reduces to function composition.
149 type CmmLivenessTransformer = CmmLive -> CmmLive
151 -- Helpers for the "Monad"
152 addLive, addKilled :: CmmLive -> CmmLivenessTransformer
153 addLive new_live live = live `unionUniqSets` new_live
154 addKilled new_killed live = live `minusUniqSet` new_killed
156 --------------------------------
157 -- Liveness of a CmmStmt
158 --------------------------------
159 cmmFormalsToLiveLocals :: HintedCmmFormals -> [LocalReg]
160 cmmFormalsToLiveLocals formals = map hintlessCmm formals
162 cmmStmtLive :: BlockEntryLiveness -> CmmStmt -> CmmLivenessTransformer
163 cmmStmtLive _ (CmmNop) = id
164 cmmStmtLive _ (CmmComment _) = id
165 cmmStmtLive _ (CmmAssign reg expr) =
166 cmmExprLive expr . reg_liveness where
169 (CmmLocal reg') -> addKilled $ unitUniqSet reg'
171 cmmStmtLive _ (CmmStore expr1 expr2) =
172 cmmExprLive expr2 . cmmExprLive expr1
173 cmmStmtLive _ (CmmCall target results arguments _ _) =
175 foldr ((.) . cmmExprLive) id (map hintlessCmm arguments) .
176 addKilled (mkUniqSet $ cmmFormalsToLiveLocals results) where
179 (CmmCallee target _) -> cmmExprLive target
181 cmmStmtLive other_live (CmmBranch target) =
182 addLive (lookupWithDefaultBEnv other_live emptyUniqSet target)
183 cmmStmtLive other_live (CmmCondBranch expr target) =
185 addLive (lookupWithDefaultBEnv other_live emptyUniqSet target)
186 cmmStmtLive other_live (CmmSwitch expr targets) =
188 (foldr ((.) . (addLive .
189 lookupWithDefaultBEnv other_live emptyUniqSet))
191 (mapCatMaybes id targets))
192 cmmStmtLive _ (CmmJump expr params) =
193 const (cmmExprLive expr $ foldr ((.) . cmmExprLive) id (map hintlessCmm params) $ emptyUniqSet)
194 cmmStmtLive _ (CmmReturn params) =
195 const (foldr ((.) . cmmExprLive) id (map hintlessCmm params) $ emptyUniqSet)
197 --------------------------------
198 -- Liveness of a CmmExpr
199 --------------------------------
200 cmmExprLive :: CmmExpr -> CmmLivenessTransformer
201 cmmExprLive expr = addLive (mkUniqSet $ expr_liveness expr) where
202 expr_liveness :: CmmExpr -> [LocalReg]
203 expr_liveness (CmmLit _) = []
204 expr_liveness (CmmLoad expr _) = expr_liveness expr
205 expr_liveness (CmmReg reg) = reg_liveness reg
206 expr_liveness (CmmMachOp _ exprs) = concatMap expr_liveness exprs
207 expr_liveness (CmmRegOff reg _) = reg_liveness reg
208 expr_liveness (CmmStackSlot _ _) = panic "cmmExprLive CmmStackSlot"
210 reg_liveness :: CmmReg -> [LocalReg]
211 reg_liveness (CmmLocal reg) = [reg]
212 reg_liveness (CmmGlobal _) = []