1 -----------------------------------------------------------------------------
3 -- The register liveness determinator
5 -- (c) The University of Glasgow 2004
7 -----------------------------------------------------------------------------
8 {-# OPTIONS -Wall -fno-warn-name-shadowing #-}
13 BlockMap, emptyBlockMap,
20 mapBlockTop, mapBlockTopM,
21 mapGenBlockTop, mapGenBlockTopM,
34 #include "HsVersions.h"
40 import Cmm hiding (RegSet)
54 -----------------------------------------------------------------------------
55 type RegSet = UniqSet Reg
57 type RegMap a = UniqFM a
59 emptyRegMap :: UniqFM a
60 emptyRegMap = emptyUFM
62 type BlockMap a = UniqFM a
64 emptyBlockMap :: UniqFM a
65 emptyBlockMap = emptyUFM
68 -- | A top level thing which carries liveness information.
73 (ListGraph (GenBasicBlock LiveInstr))
74 -- the "instructions" here are actually more blocks,
75 -- single blocks are acyclic
76 -- multiple blocks are taken to be cyclic.
78 -- | An instruction with liveness information.
80 = Instr Instr (Maybe Liveness)
82 -- | Liveness information.
83 -- The regs which die are ones which are no longer live in the *next* instruction
85 -- (NB. if the instruction is a jump, these registers might still be live
86 -- at the jump target(s) - you have to check the liveness at the destination
87 -- block to find out).
91 { liveBorn :: RegSet -- ^ registers born in this instruction (written to for first time).
92 , liveDieRead :: RegSet -- ^ registers that died because they were read for the last time.
93 , liveDieWrite :: RegSet } -- ^ registers that died because they were clobbered by something.
96 -- | Stash regs live on entry to each basic block in the info part of the cmm code.
99 [CmmStatic] -- cmm static stuff
100 (Maybe BlockId) -- id of the first block
101 (BlockMap RegSet) -- argument locals live on entry to this block
103 -- | A basic block with liveness information.
105 = GenBasicBlock LiveInstr
108 instance Outputable LiveInstr where
109 ppr (Instr instr Nothing)
112 ppr (Instr instr (Just live))
116 [ pprRegs (ptext SLIT("# born: ")) (liveBorn live)
117 , pprRegs (ptext SLIT("# r_dying: ")) (liveDieRead live)
118 , pprRegs (ptext SLIT("# w_dying: ")) (liveDieWrite live) ]
121 where pprRegs :: SDoc -> RegSet -> SDoc
123 | isEmptyUniqSet regs = empty
124 | otherwise = name <> (hcat $ punctuate space $ map (docToSDoc . pprUserReg) $ uniqSetToList regs)
127 instance Outputable LiveInfo where
128 ppr (LiveInfo static firstId liveOnEntry)
129 = (vcat $ map ppr static)
130 $$ text "# firstId = " <> ppr firstId
131 $$ text "# liveOnEntry = " <> ppr liveOnEntry
134 -- | map a function across all the basic blocks in this code
137 :: (LiveBasicBlock -> LiveBasicBlock)
138 -> LiveCmmTop -> LiveCmmTop
141 = evalState (mapBlockTopM (\x -> return $ f x) cmm) ()
144 -- | map a function across all the basic blocks in this code (monadic version)
148 => (LiveBasicBlock -> m LiveBasicBlock)
149 -> LiveCmmTop -> m LiveCmmTop
151 mapBlockTopM _ cmm@(CmmData{})
154 mapBlockTopM f (CmmProc header label params (ListGraph comps))
155 = do comps' <- mapM (mapBlockCompM f) comps
156 return $ CmmProc header label params (ListGraph comps')
158 mapBlockCompM :: Monad m => (a -> m a') -> (GenBasicBlock a) -> m (GenBasicBlock a')
159 mapBlockCompM f (BasicBlock i blocks)
160 = do blocks' <- mapM f blocks
161 return $ BasicBlock i blocks'
164 -- map a function across all the basic blocks in this code
166 :: (GenBasicBlock i -> GenBasicBlock i)
167 -> (GenCmmTop d h (ListGraph i) -> GenCmmTop d h (ListGraph i))
170 = evalState (mapGenBlockTopM (\x -> return $ f x) cmm) ()
173 -- | map a function across all the basic blocks in this code (monadic version)
176 => (GenBasicBlock i -> m (GenBasicBlock i))
177 -> (GenCmmTop d h (ListGraph i) -> m (GenCmmTop d h (ListGraph i)))
179 mapGenBlockTopM _ cmm@(CmmData{})
182 mapGenBlockTopM f (CmmProc header label params (ListGraph blocks))
183 = do blocks' <- mapM f blocks
184 return $ CmmProc header label params (ListGraph blocks')
187 -- | Slurp out the list of register conflicts and reg-reg moves from this top level thing.
188 -- Slurping of conflicts and moves is wrapped up together so we don't have
189 -- to make two passes over the same code when we want to build the graph.
191 slurpConflicts :: LiveCmmTop -> (Bag (UniqSet Reg), Bag (Reg, Reg))
193 = slurpCmm (emptyBag, emptyBag) live
195 where slurpCmm rs CmmData{} = rs
196 slurpCmm rs (CmmProc info _ _ (ListGraph blocks))
197 = foldl' (slurpComp info) rs blocks
199 slurpComp info rs (BasicBlock _ blocks)
200 = foldl' (slurpBlock info) rs blocks
202 slurpBlock info rs (BasicBlock blockId instrs)
203 | LiveInfo _ _ blockLive <- info
204 , Just rsLiveEntry <- lookupUFM blockLive blockId
205 , (conflicts, moves) <- slurpLIs rsLiveEntry rs instrs
206 = (consBag rsLiveEntry conflicts, moves)
209 = error "RegLiveness.slurpBlock: bad block"
211 slurpLIs rsLive (conflicts, moves) []
212 = (consBag rsLive conflicts, moves)
214 slurpLIs rsLive rs (Instr _ Nothing : lis) = slurpLIs rsLive rs lis
216 slurpLIs rsLiveEntry (conflicts, moves) (Instr instr (Just live) : lis)
218 -- regs that die because they are read for the last time at the start of an instruction
219 -- are not live across it.
220 rsLiveAcross = rsLiveEntry `minusUniqSet` (liveDieRead live)
222 -- regs live on entry to the next instruction.
223 -- be careful of orphans, make sure to delete dying regs _after_ unioning
224 -- in the ones that are born here.
225 rsLiveNext = (rsLiveAcross `unionUniqSets` (liveBorn live))
226 `minusUniqSet` (liveDieWrite live)
228 -- orphan vregs are the ones that die in the same instruction they are born in.
229 -- these are likely to be results that are never used, but we still
230 -- need to assign a hreg to them..
231 rsOrphans = intersectUniqSets
233 (unionUniqSets (liveDieWrite live) (liveDieRead live))
236 rsConflicts = unionUniqSets rsLiveNext rsOrphans
238 in case isRegRegMove instr of
239 Just rr -> slurpLIs rsLiveNext
240 ( consBag rsConflicts conflicts
241 , consBag rr moves) lis
243 Nothing -> slurpLIs rsLiveNext
244 ( consBag rsConflicts conflicts
248 -- | For spill/reloads
254 -- If we can arrange that v1 and v2 are allocated to the same hreg it's more likely
255 -- the spill/reload instrs can be cleaned and replaced by a nop reg-reg move.
257 -- TODO: This only works intra-block at the momement. It's be nice to join up the mappings
258 -- across blocks also.
260 slurpReloadCoalesce :: LiveCmmTop -> Bag (Reg, Reg)
261 slurpReloadCoalesce live
262 = slurpCmm emptyBag live
264 where slurpCmm cs CmmData{} = cs
265 slurpCmm cs (CmmProc _ _ _ (ListGraph blocks))
266 = foldl' slurpComp cs blocks
268 slurpComp cs (BasicBlock _ blocks)
269 = foldl' slurpBlock cs blocks
271 slurpBlock cs (BasicBlock _ instrs)
272 = let (_, mMoves) = mapAccumL slurpLI emptyUFM instrs
273 in unionBags cs (listToBag $ catMaybes mMoves)
275 slurpLI :: UniqFM Reg -> LiveInstr -> (UniqFM Reg, Maybe (Reg, Reg))
276 slurpLI slotMap (Instr instr _)
278 -- remember what reg was stored into the slot
279 | SPILL reg slot <- instr
280 , slotMap' <- addToUFM slotMap slot reg
281 = (slotMap', Nothing)
283 -- add an edge betwen the this reg and the last one stored into the slot
284 | RELOAD slot reg <- instr
285 = case lookupUFM slotMap slot of
287 | reg /= reg2 -> (slotMap, Just (reg, reg2))
288 | otherwise -> (slotMap, Nothing)
290 Nothing -> (slotMap, Nothing)
296 -- | Strip away liveness information, yielding NatCmmTop
298 stripLive :: LiveCmmTop -> NatCmmTop
302 where stripCmm (CmmData sec ds) = CmmData sec ds
303 stripCmm (CmmProc (LiveInfo info _ _) label params (ListGraph comps))
304 = CmmProc info label params (ListGraph $ concatMap stripComp comps)
306 stripComp (BasicBlock _ blocks) = map stripBlock blocks
307 stripBlock (BasicBlock i instrs) = BasicBlock i (map stripLI instrs)
308 stripLI (Instr instr _) = instr
311 -- | Make real spill instructions out of SPILL, RELOAD pseudos
313 spillNatBlock :: NatBasicBlock -> NatBasicBlock
314 spillNatBlock (BasicBlock i is)
315 = BasicBlock i instrs'
317 = runState (spillNat [] is) 0
320 = return (reverse acc)
322 spillNat acc (DELTA i : instrs)
326 spillNat acc (SPILL reg slot : instrs)
328 spillNat (mkSpillInstr reg delta slot : acc) instrs
330 spillNat acc (RELOAD slot reg : instrs)
332 spillNat (mkLoadInstr reg delta slot : acc) instrs
334 spillNat acc (instr : instrs)
335 = spillNat (instr : acc) instrs
338 -- | Slurp out a map of how many times each register was live upon entry to an instruction.
342 -> UniqFM (Reg, Int) -- ^ reg -> (reg, count)
345 = countCmm emptyUFM cmm
347 countCmm fm CmmData{} = fm
348 countCmm fm (CmmProc info _ _ (ListGraph blocks))
349 = foldl' (countComp info) fm blocks
351 countComp info fm (BasicBlock _ blocks)
352 = foldl' (countBlock info) fm blocks
354 countBlock info fm (BasicBlock blockId instrs)
355 | LiveInfo _ _ blockLive <- info
356 , Just rsLiveEntry <- lookupUFM blockLive blockId
357 = countLIs rsLiveEntry fm instrs
360 = error "RegLiveness.countBlock: bad block"
362 countLIs _ fm [] = fm
363 countLIs rsLive fm (Instr _ Nothing : lis) = countLIs rsLive fm lis
365 countLIs rsLiveEntry fm (Instr _ (Just live) : lis)
367 rsLiveAcross = rsLiveEntry `minusUniqSet` (liveDieRead live)
369 rsLiveNext = (rsLiveAcross `unionUniqSets` (liveBorn live))
370 `minusUniqSet` (liveDieWrite live)
372 add r fm = addToUFM_C
373 (\(r1, l1) (_, l2) -> (r1, l1 + l2))
376 fm' = foldUniqSet add fm rsLiveEntry
377 in countLIs rsLiveNext fm' lis
380 -- | Erase Delta instructions.
382 eraseDeltasLive :: LiveCmmTop -> LiveCmmTop
384 = mapBlockTop eraseBlock cmm
386 isDelta (DELTA _) = True
389 eraseBlock (BasicBlock id lis)
391 $ filter (\(Instr i _) -> not $ isDelta i)
395 -- | Patch the registers in this code according to this register mapping.
396 -- also erase reg -> reg moves when the reg is the same.
397 -- also erase reg -> reg moves when the destination dies in this instr.
401 -> LiveCmmTop -> LiveCmmTop
403 patchEraseLive patchF cmm
406 patchCmm cmm@CmmData{} = cmm
408 patchCmm (CmmProc info label params (ListGraph comps))
409 | LiveInfo static id blockMap <- info
410 = let patchRegSet set = mkUniqSet $ map patchF $ uniqSetToList set
411 blockMap' = mapUFM patchRegSet blockMap
413 info' = LiveInfo static id blockMap'
414 in CmmProc info' label params $ ListGraph $ map patchComp comps
416 patchComp (BasicBlock id blocks)
417 = BasicBlock id $ map patchBlock blocks
419 patchBlock (BasicBlock id lis)
420 = BasicBlock id $ patchInstrs lis
423 patchInstrs (li : lis)
425 | Instr i (Just live) <- li'
426 , Just (r1, r2) <- isRegRegMove i
431 = li' : patchInstrs lis
433 where li' = patchRegsLiveInstr patchF li
436 -- source and destination regs are the same
439 -- desination reg is never used
440 | elementOfUniqSet r2 (liveBorn live)
441 , elementOfUniqSet r2 (liveDieRead live) || elementOfUniqSet r2 (liveDieWrite live)
447 -- | Patch registers in this LiveInstr, including the liveness information.
451 -> LiveInstr -> LiveInstr
453 patchRegsLiveInstr patchF li
456 -> Instr (patchRegs instr patchF) Nothing
458 Instr instr (Just live)
460 (patchRegs instr patchF)
462 { -- WARNING: have to go via lists here because patchF changes the uniq in the Reg
463 liveBorn = mkUniqSet $ map patchF $ uniqSetToList $ liveBorn live
464 , liveDieRead = mkUniqSet $ map patchF $ uniqSetToList $ liveDieRead live
465 , liveDieWrite = mkUniqSet $ map patchF $ uniqSetToList $ liveDieWrite live })
468 ---------------------------------------------------------------------------------
469 -- Annotate code with register liveness information
475 regLiveness (CmmData i d)
476 = returnUs $ CmmData i d
478 regLiveness (CmmProc info lbl params (ListGraph []))
480 (LiveInfo info Nothing emptyUFM)
481 lbl params (ListGraph [])
483 regLiveness (CmmProc info lbl params (ListGraph blocks@(first : _)))
484 = let first_id = blockId first
485 sccs = sccBlocks blocks
486 (ann_sccs, block_live) = computeLiveness sccs
489 = map (\scc -> case scc of
490 AcyclicSCC b@(BasicBlock l _) -> BasicBlock l [b]
491 CyclicSCC bs@(BasicBlock l _ : _) -> BasicBlock l bs
493 -> panic "RegLiveness.regLiveness: no blocks in scc list")
496 in returnUs $ CmmProc
497 (LiveInfo info (Just first_id) block_live)
498 lbl params (ListGraph liveBlocks)
501 sccBlocks :: [NatBasicBlock] -> [SCC NatBasicBlock]
502 sccBlocks blocks = stronglyConnComp graph
504 getOutEdges :: [Instr] -> [BlockId]
505 getOutEdges instrs = foldl' (\a x -> jumpDests x a) [] instrs
507 graph = [ (block, getUnique id, map getUnique (getOutEdges instrs))
508 | block@(BasicBlock id instrs) <- blocks ]
511 -- -----------------------------------------------------------------------------
512 -- Computing liveness
515 :: [SCC NatBasicBlock]
516 -> ([SCC LiveBasicBlock], -- instructions annotated with list of registers
517 -- which are "dead after this instruction".
518 BlockMap RegSet) -- blocks annontated with set of live registers
519 -- on entry to the block.
521 -- NOTE: on entry, the SCCs are in "reverse" order: later blocks may transfer
522 -- control to earlier ones only. The SCCs returned are in the *opposite*
523 -- order, which is exactly what we want for the next pass.
526 = livenessSCCs emptyBlockMap [] sccs
531 -> [SCC LiveBasicBlock] -- accum
532 -> [SCC NatBasicBlock]
533 -> ([SCC LiveBasicBlock], BlockMap RegSet)
535 livenessSCCs blockmap done [] = (done, blockmap)
537 livenessSCCs blockmap done (AcyclicSCC block : sccs)
538 = let (blockmap', block') = livenessBlock blockmap block
539 in livenessSCCs blockmap' (AcyclicSCC block' : done) sccs
541 livenessSCCs blockmap done
542 (CyclicSCC blocks : sccs) =
543 livenessSCCs blockmap' (CyclicSCC blocks':done) sccs
544 where (blockmap', blocks')
545 = iterateUntilUnchanged linearLiveness equalBlockMaps
548 iterateUntilUnchanged
549 :: (a -> b -> (a,c)) -> (a -> a -> Bool)
553 iterateUntilUnchanged f eq a b
556 groupBy (\(a1, _) (a2, _) -> eq a1 a2) $
557 iterate (\(a, _) -> f a b) $
558 (a, error "RegisterAlloc.livenessSCCs")
561 linearLiveness :: BlockMap RegSet -> [NatBasicBlock]
562 -> (BlockMap RegSet, [LiveBasicBlock])
563 linearLiveness = mapAccumL livenessBlock
565 -- probably the least efficient way to compare two
566 -- BlockMaps for equality.
569 where a' = map f $ ufmToList a
570 b' = map f $ ufmToList b
571 f (key,elt) = (key, uniqSetToList elt)
575 -- | Annotate a basic block with register liveness information.
580 -> (BlockMap RegSet, LiveBasicBlock)
582 livenessBlock blockmap (BasicBlock block_id instrs)
584 (regsLiveOnEntry, instrs1)
585 = livenessBack emptyUniqSet blockmap [] (reverse instrs)
586 blockmap' = addToUFM blockmap block_id regsLiveOnEntry
588 instrs2 = livenessForward regsLiveOnEntry instrs1
590 output = BasicBlock block_id instrs2
592 in ( blockmap', output)
594 -- | Calculate liveness going forwards,
595 -- filling in when regs are born
598 :: RegSet -- regs live on this instr
599 -> [LiveInstr] -> [LiveInstr]
601 livenessForward _ [] = []
602 livenessForward rsLiveEntry (li@(Instr instr mLive) : lis)
604 = li : livenessForward rsLiveEntry lis
607 , RU _ written <- regUsage instr
609 -- Regs that are written to but weren't live on entry to this instruction
610 -- are recorded as being born here.
612 $ filter (\r -> not $ elementOfUniqSet r rsLiveEntry) written
614 rsLiveNext = (rsLiveEntry `unionUniqSets` rsBorn)
615 `minusUniqSet` (liveDieRead live)
616 `minusUniqSet` (liveDieWrite live)
618 in Instr instr (Just live { liveBorn = rsBorn })
619 : livenessForward rsLiveNext lis
621 livenessForward _ _ = panic "RegLiveness.livenessForward: no match"
624 -- | Calculate liveness going backwards,
625 -- filling in when regs die, and what regs are live across each instruction
628 :: RegSet -- regs live on this instr
629 -> BlockMap RegSet -- regs live on entry to other BBs
630 -> [LiveInstr] -- instructions (accum)
631 -> [Instr] -- instructions
632 -> (RegSet, [LiveInstr])
634 livenessBack liveregs _ done [] = (liveregs, done)
636 livenessBack liveregs blockmap acc (instr : instrs)
637 = let (liveregs', instr') = liveness1 liveregs blockmap instr
638 in livenessBack liveregs' blockmap (instr' : acc) instrs
640 -- don't bother tagging comments or deltas with liveness
641 liveness1 :: RegSet -> BlockMap RegSet -> Instr -> (RegSet, LiveInstr)
642 liveness1 liveregs _ (instr@COMMENT{})
643 = (liveregs, Instr instr Nothing)
645 liveness1 liveregs _ (instr@DELTA{})
646 = (liveregs, Instr instr Nothing)
648 liveness1 liveregs blockmap instr
651 = (liveregs1, Instr instr
653 { liveBorn = emptyUniqSet
654 , liveDieRead = mkUniqSet r_dying
655 , liveDieWrite = mkUniqSet w_dying }))
658 = (liveregs_br, Instr instr
660 { liveBorn = emptyUniqSet
661 , liveDieRead = mkUniqSet r_dying_br
662 , liveDieWrite = mkUniqSet w_dying }))
665 RU read written = regUsage instr
667 -- registers that were written here are dead going backwards.
668 -- registers that were read here are live going backwards.
669 liveregs1 = (liveregs `delListFromUniqSet` written)
670 `addListToUniqSet` read
672 -- registers that are not live beyond this point, are recorded
674 r_dying = [ reg | reg <- read, reg `notElem` written,
675 not (elementOfUniqSet reg liveregs) ]
677 w_dying = [ reg | reg <- written,
678 not (elementOfUniqSet reg liveregs) ]
680 -- union in the live regs from all the jump destinations of this
682 targets = jumpDests instr [] -- where we go from here
683 not_a_branch = null targets
685 targetLiveRegs target
686 = case lookupUFM blockmap target of
688 Nothing -> emptyBlockMap
690 live_from_branch = unionManyUniqSets (map targetLiveRegs targets)
692 liveregs_br = liveregs1 `unionUniqSets` live_from_branch
694 -- registers that are live only in the branch targets should
695 -- be listed as dying here.
696 live_branch_only = live_from_branch `minusUniqSet` liveregs
697 r_dying_br = uniqSetToList (mkUniqSet r_dying `unionUniqSets`