1 -----------------------------------------------------------------------------
3 -- The register liveness determinator
5 -- (c) The University of Glasgow 2004
7 -----------------------------------------------------------------------------
8 {-# OPTIONS -Wall -fno-warn-name-shadowing #-}
10 module RegAlloc.Liveness (
13 BlockMap, emptyBlockMap,
20 mapBlockTop, mapBlockTopM,
21 mapGenBlockTop, mapGenBlockTopM,
38 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 = BlockEnv a
64 emptyBlockMap :: BlockEnv a
65 emptyBlockMap = emptyBlockEnv
68 -- | A top level thing which carries liveness information.
73 [SCC (LiveBasicBlock instr)]
76 -- | An instruction with liveness information.
78 = Instr instr (Maybe Liveness)
80 -- | spill this reg to a stack slot
83 -- | reload this reg from a stack slot
87 -- | Liveness information.
88 -- The regs which die are ones which are no longer live in the *next* instruction
90 -- (NB. if the instruction is a jump, these registers might still be live
91 -- at the jump target(s) - you have to check the liveness at the destination
92 -- block to find out).
96 { liveBorn :: RegSet -- ^ registers born in this instruction (written to for first time).
97 , liveDieRead :: RegSet -- ^ registers that died because they were read for the last time.
98 , liveDieWrite :: RegSet } -- ^ registers that died because they were clobbered by something.
101 -- | Stash regs live on entry to each basic block in the info part of the cmm code.
104 [CmmStatic] -- cmm static stuff
105 (Maybe BlockId) -- id of the first block
106 (Maybe (BlockMap RegSet)) -- argument locals live on entry to this block
108 -- | A basic block with liveness information.
109 type LiveBasicBlock instr
110 = GenBasicBlock (LiveInstr instr)
113 instance Outputable instr
114 => Outputable (LiveInstr instr) where
117 ptext (sLit "\tSPILL"),
121 ptext (sLit "SLOT") <> parens (int slot)]
123 ppr (RELOAD slot reg)
125 ptext (sLit "\tRELOAD"),
127 ptext (sLit "SLOT") <> parens (int slot),
131 ppr (Instr instr Nothing)
134 ppr (Instr instr (Just live))
138 [ pprRegs (ptext (sLit "# born: ")) (liveBorn live)
139 , pprRegs (ptext (sLit "# r_dying: ")) (liveDieRead live)
140 , pprRegs (ptext (sLit "# w_dying: ")) (liveDieWrite live) ]
143 where pprRegs :: SDoc -> RegSet -> SDoc
145 | isEmptyUniqSet regs = empty
146 | otherwise = name <> (hcat $ punctuate space $ map ppr $ uniqSetToList regs)
148 instance Outputable LiveInfo where
149 ppr (LiveInfo static firstId liveOnEntry)
150 = (vcat $ map ppr static)
151 $$ text "# firstId = " <> ppr firstId
152 $$ text "# liveOnEntry = " <> ppr liveOnEntry
156 -- | map a function across all the basic blocks in this code
159 :: (LiveBasicBlock instr -> LiveBasicBlock instr)
160 -> LiveCmmTop instr -> LiveCmmTop instr
163 = evalState (mapBlockTopM (\x -> return $ f x) cmm) ()
166 -- | map a function across all the basic blocks in this code (monadic version)
170 => (LiveBasicBlock instr -> m (LiveBasicBlock instr))
171 -> LiveCmmTop instr -> m (LiveCmmTop instr)
173 mapBlockTopM _ cmm@(CmmData{})
176 mapBlockTopM f (CmmProc header label params sccs)
177 = do sccs' <- mapM (mapSCCM f) sccs
178 return $ CmmProc header label params sccs'
180 mapSCCM :: Monad m => (a -> m b) -> SCC a -> m (SCC b)
181 mapSCCM f (AcyclicSCC x)
183 return $ AcyclicSCC x'
185 mapSCCM f (CyclicSCC xs)
186 = do xs' <- mapM f xs
187 return $ CyclicSCC xs'
190 mapBlockCompM :: Monad m => (a -> m a') -> (GenBasicBlock a) -> m (GenBasicBlock a')
191 mapBlockCompM f (BasicBlock i blocks)
192 = do blocks' <- mapM f blocks
193 return $ BasicBlock i blocks'
196 -- map a function across all the basic blocks in this code
198 :: (GenBasicBlock i -> GenBasicBlock i)
199 -> (GenCmmTop d h (ListGraph i) -> GenCmmTop d h (ListGraph i))
202 = evalState (mapGenBlockTopM (\x -> return $ f x) cmm) ()
205 -- | map a function across all the basic blocks in this code (monadic version)
208 => (GenBasicBlock i -> m (GenBasicBlock i))
209 -> (GenCmmTop d h (ListGraph i) -> m (GenCmmTop d h (ListGraph i)))
211 mapGenBlockTopM _ cmm@(CmmData{})
214 mapGenBlockTopM f (CmmProc header label params (ListGraph blocks))
215 = do blocks' <- mapM f blocks
216 return $ CmmProc header label params (ListGraph blocks')
219 -- | Slurp out the list of register conflicts and reg-reg moves from this top level thing.
220 -- Slurping of conflicts and moves is wrapped up together so we don't have
221 -- to make two passes over the same code when we want to build the graph.
226 -> (Bag (UniqSet Reg), Bag (Reg, Reg))
229 = slurpCmm (emptyBag, emptyBag) live
231 where slurpCmm rs CmmData{} = rs
232 slurpCmm rs (CmmProc info _ _ sccs)
233 = foldl' (slurpSCC info) rs sccs
235 slurpSCC info rs (AcyclicSCC b)
236 = slurpBlock info rs b
238 slurpSCC info rs (CyclicSCC bs)
239 = foldl' (slurpBlock info) rs bs
241 slurpBlock info rs (BasicBlock blockId instrs)
242 | LiveInfo _ _ (Just blockLive) <- info
243 , Just rsLiveEntry <- lookupBlockEnv blockLive blockId
244 , (conflicts, moves) <- slurpLIs rsLiveEntry rs instrs
245 = (consBag rsLiveEntry conflicts, moves)
248 = panic "Liveness.slurpConflicts: bad block"
250 slurpLIs rsLive (conflicts, moves) []
251 = (consBag rsLive conflicts, moves)
253 slurpLIs rsLive rs (Instr _ Nothing : lis)
254 = slurpLIs rsLive rs lis
256 -- we're not expecting to be slurping conflicts from spilled code
257 slurpLIs _ _ (SPILL _ _ : _)
258 = panic "Liveness.slurpConflicts: unexpected SPILL"
260 slurpLIs _ _ (RELOAD _ _ : _)
261 = panic "Liveness.slurpConflicts: unexpected RELOAD"
263 slurpLIs rsLiveEntry (conflicts, moves) (Instr instr (Just live) : lis)
265 -- regs that die because they are read for the last time at the start of an instruction
266 -- are not live across it.
267 rsLiveAcross = rsLiveEntry `minusUniqSet` (liveDieRead live)
269 -- regs live on entry to the next instruction.
270 -- be careful of orphans, make sure to delete dying regs _after_ unioning
271 -- in the ones that are born here.
272 rsLiveNext = (rsLiveAcross `unionUniqSets` (liveBorn live))
273 `minusUniqSet` (liveDieWrite live)
275 -- orphan vregs are the ones that die in the same instruction they are born in.
276 -- these are likely to be results that are never used, but we still
277 -- need to assign a hreg to them..
278 rsOrphans = intersectUniqSets
280 (unionUniqSets (liveDieWrite live) (liveDieRead live))
283 rsConflicts = unionUniqSets rsLiveNext rsOrphans
285 in case takeRegRegMoveInstr instr of
286 Just rr -> slurpLIs rsLiveNext
287 ( consBag rsConflicts conflicts
288 , consBag rr moves) lis
290 Nothing -> slurpLIs rsLiveNext
291 ( consBag rsConflicts conflicts
295 -- | For spill\/reloads
301 -- If we can arrange that v1 and v2 are allocated to the same hreg it's more likely
302 -- the spill\/reload instrs can be cleaned and replaced by a nop reg-reg move.
310 slurpReloadCoalesce live
311 = slurpCmm emptyBag live
313 where slurpCmm cs CmmData{} = cs
314 slurpCmm cs (CmmProc _ _ _ sccs)
315 = slurpComp cs (flattenSCCs sccs)
318 = let (moveBags, _) = runState (slurpCompM blocks) emptyUFM
319 in unionManyBags (cs : moveBags)
322 = do -- run the analysis once to record the mapping across jumps.
323 mapM_ (slurpBlock False) blocks
325 -- run it a second time while using the information from the last pass.
326 -- We /could/ run this many more times to deal with graphical control
327 -- flow and propagating info across multiple jumps, but it's probably
328 -- not worth the trouble.
329 mapM (slurpBlock True) blocks
331 slurpBlock propagate (BasicBlock blockId instrs)
332 = do -- grab the slot map for entry to this block
333 slotMap <- if propagate
334 then getSlotMap blockId
337 (_, mMoves) <- mapAccumLM slurpLI slotMap instrs
338 return $ listToBag $ catMaybes mMoves
340 slurpLI :: Instruction instr
341 => UniqFM Reg -- current slotMap
343 -> State (UniqFM [UniqFM Reg]) -- blockId -> [slot -> reg]
344 -- for tracking slotMaps across jumps
346 ( UniqFM Reg -- new slotMap
347 , Maybe (Reg, Reg)) -- maybe a new coalesce edge
351 -- remember what reg was stored into the slot
352 | SPILL reg slot <- li
353 , slotMap' <- addToUFM slotMap slot reg
354 = return (slotMap', Nothing)
356 -- add an edge betwen the this reg and the last one stored into the slot
357 | RELOAD slot reg <- li
358 = case lookupUFM slotMap slot of
360 | reg /= reg2 -> return (slotMap, Just (reg, reg2))
361 | otherwise -> return (slotMap, Nothing)
363 Nothing -> return (slotMap, Nothing)
365 -- if we hit a jump, remember the current slotMap
366 | Instr instr _ <- li
367 , targets <- jumpDestsOfInstr instr
369 = do mapM_ (accSlotMap slotMap) targets
370 return (slotMap, Nothing)
373 = return (slotMap, Nothing)
375 -- record a slotmap for an in edge to this block
376 accSlotMap slotMap blockId
377 = modify (\s -> addToUFM_C (++) s blockId [slotMap])
379 -- work out the slot map on entry to this block
380 -- if we have slot maps for multiple in-edges then we need to merge them.
383 let slotMaps = fromMaybe [] (lookupUFM map blockId)
384 return $ foldr mergeSlotMaps emptyUFM slotMaps
386 mergeSlotMaps :: UniqFM Reg -> UniqFM Reg -> UniqFM Reg
387 mergeSlotMaps map1 map2
389 $ [ (k, r1) | (k, r1) <- ufmToList map1
390 , case lookupUFM map2 k of
392 Just r2 -> r1 == r2 ]
395 -- | Strip away liveness information, yielding NatCmmTop
405 where stripCmm (CmmData sec ds) = CmmData sec ds
406 stripCmm (CmmProc (LiveInfo info _ _) label params sccs)
407 = CmmProc info label params
408 (ListGraph $ map stripLiveBlock $ flattenSCCs sccs)
411 -- | Strip away liveness information from a basic block,
412 -- and make real spill instructions out of SPILL, RELOAD pseudos along the way.
416 => LiveBasicBlock instr
417 -> NatBasicBlock instr
419 stripLiveBlock (BasicBlock i lis)
420 = BasicBlock i instrs'
423 = runState (spillNat [] lis) 0
426 = return (reverse acc)
428 spillNat acc (SPILL reg slot : instrs)
430 spillNat (mkSpillInstr reg delta slot : acc) instrs
432 spillNat acc (RELOAD slot reg : instrs)
434 spillNat (mkLoadInstr reg delta slot : acc) instrs
436 spillNat acc (Instr instr _ : instrs)
437 | Just i <- takeDeltaInstr instr
441 spillNat acc (Instr instr _ : instrs)
442 = spillNat (instr : acc) instrs
445 -- | Erase Delta instructions.
453 = mapBlockTop eraseBlock cmm
455 eraseBlock (BasicBlock id lis)
457 $ filter (\(Instr i _) -> not $ isJust $ takeDeltaInstr i)
461 -- | Patch the registers in this code according to this register mapping.
462 -- also erase reg -> reg moves when the reg is the same.
463 -- also erase reg -> reg moves when the destination dies in this instr.
468 -> LiveCmmTop instr -> LiveCmmTop instr
470 patchEraseLive patchF cmm
473 patchCmm cmm@CmmData{} = cmm
475 patchCmm (CmmProc info label params sccs)
476 | LiveInfo static id (Just blockMap) <- info
478 patchRegSet set = mkUniqSet $ map patchF $ uniqSetToList set
479 blockMap' = mapBlockEnv patchRegSet blockMap
481 info' = LiveInfo static id (Just blockMap')
482 in CmmProc info' label params $ map patchSCC sccs
485 = panic "RegAlloc.Liveness.patchEraseLive: no blockMap"
487 patchSCC (AcyclicSCC b) = AcyclicSCC (patchBlock b)
488 patchSCC (CyclicSCC bs) = CyclicSCC (map patchBlock bs)
490 patchBlock (BasicBlock id lis)
491 = BasicBlock id $ patchInstrs lis
494 patchInstrs (li : lis)
496 | Instr i (Just live) <- li'
497 , Just (r1, r2) <- takeRegRegMoveInstr i
502 = li' : patchInstrs lis
504 where li' = patchRegsLiveInstr patchF li
507 -- source and destination regs are the same
510 -- desination reg is never used
511 | elementOfUniqSet r2 (liveBorn live)
512 , elementOfUniqSet r2 (liveDieRead live) || elementOfUniqSet r2 (liveDieWrite live)
518 -- | Patch registers in this LiveInstr, including the liveness information.
523 -> LiveInstr instr -> LiveInstr instr
525 patchRegsLiveInstr patchF li
528 -> Instr (patchRegsOfInstr instr patchF) Nothing
530 Instr instr (Just live)
532 (patchRegsOfInstr instr patchF)
534 { -- WARNING: have to go via lists here because patchF changes the uniq in the Reg
535 liveBorn = mkUniqSet $ map patchF $ uniqSetToList $ liveBorn live
536 , liveDieRead = mkUniqSet $ map patchF $ uniqSetToList $ liveDieRead live
537 , liveDieWrite = mkUniqSet $ map patchF $ uniqSetToList $ liveDieWrite live })
540 -> SPILL (patchF reg) slot
543 -> RELOAD slot (patchF reg)
546 --------------------------------------------------------------------------------
547 -- | Convert a NatCmmTop to a LiveCmmTop, with empty liveness information
553 natCmmTopToLive cmm@(CmmData _ _)
556 natCmmTopToLive (CmmProc info lbl params (ListGraph []))
557 = CmmProc (LiveInfo info Nothing emptyBlockEnv)
558 lbl params (ListGraph []))
560 natCmmTopToLive (CmmProc info lbl params (ListGraph blocks))
561 = let first_id = blockId first
562 sccs = sccBlocks blocks
565 = map (\scc -> case scc of
566 AcyclicSCC b@(BasicBlock l _) -> BasicBlock l [cmmBlockToLive b]
567 CyclicSCC bs@(BasicBlock l _ : _) -> BasicBlock l (map cmmBlockToLive bs)
569 -> panic "RegLiveNess.natCmmTopToLive: no blocks in scc list")
572 in CmmProc (LiveInfo info (Just first_id) ???
575 ---------------------------------------------------------------------------------
576 -- Annotate code with register liveness information
581 -> UniqSM (LiveCmmTop instr)
583 regLiveness (CmmData i d)
584 = returnUs $ CmmData i d
586 regLiveness (CmmProc info lbl params (ListGraph []))
588 (LiveInfo info Nothing (Just emptyBlockEnv))
591 regLiveness (CmmProc info lbl params (ListGraph blocks@(first : _)))
592 = let first_id = blockId first
593 sccs = sccBlocks blocks
594 (ann_sccs, block_live) = computeLiveness sccs
596 in returnUs $ CmmProc (LiveInfo info (Just first_id) (Just block_live))
602 => [NatBasicBlock instr]
603 -> [SCC (NatBasicBlock instr)]
605 sccBlocks blocks = stronglyConnCompFromEdgedVertices graph
607 getOutEdges :: Instruction instr => [instr] -> [BlockId]
608 getOutEdges instrs = concat $ map jumpDestsOfInstr instrs
610 graph = [ (block, getUnique id, map getUnique (getOutEdges instrs))
611 | block@(BasicBlock id instrs) <- blocks ]
614 -- -----------------------------------------------------------------------------
615 -- Computing liveness
619 => [SCC (NatBasicBlock instr)]
620 -> ([SCC (LiveBasicBlock instr)], -- instructions annotated with list of registers
621 -- which are "dead after this instruction".
622 BlockMap RegSet) -- blocks annontated with set of live registers
623 -- on entry to the block.
625 -- NOTE: on entry, the SCCs are in "reverse" order: later blocks may transfer
626 -- control to earlier ones only. The SCCs returned are in the *opposite*
627 -- order, which is exactly what we want for the next pass.
630 = livenessSCCs emptyBlockMap [] sccs
636 -> [SCC (LiveBasicBlock instr)] -- accum
637 -> [SCC (NatBasicBlock instr)]
638 -> ( [SCC (LiveBasicBlock instr)]
641 livenessSCCs blockmap done [] = (done, blockmap)
643 livenessSCCs blockmap done (AcyclicSCC block : sccs)
644 = let (blockmap', block') = livenessBlock blockmap block
645 in livenessSCCs blockmap' (AcyclicSCC block' : done) sccs
647 livenessSCCs blockmap done
648 (CyclicSCC blocks : sccs) =
649 livenessSCCs blockmap' (CyclicSCC blocks':done) sccs
650 where (blockmap', blocks')
651 = iterateUntilUnchanged linearLiveness equalBlockMaps
654 iterateUntilUnchanged
655 :: (a -> b -> (a,c)) -> (a -> a -> Bool)
659 iterateUntilUnchanged f eq a b
662 groupBy (\(a1, _) (a2, _) -> eq a1 a2) $
663 iterate (\(a, _) -> f a b) $
664 (a, panic "RegLiveness.livenessSCCs")
669 => BlockMap RegSet -> [NatBasicBlock instr]
670 -> (BlockMap RegSet, [LiveBasicBlock instr])
672 linearLiveness = mapAccumL livenessBlock
674 -- probably the least efficient way to compare two
675 -- BlockMaps for equality.
678 where a' = map f $ blockEnvToList a
679 b' = map f $ blockEnvToList b
680 f (key,elt) = (key, uniqSetToList elt)
684 -- | Annotate a basic block with register liveness information.
689 -> NatBasicBlock instr
690 -> (BlockMap RegSet, LiveBasicBlock instr)
692 livenessBlock blockmap (BasicBlock block_id instrs)
694 (regsLiveOnEntry, instrs1)
695 = livenessBack emptyUniqSet blockmap [] (reverse instrs)
696 blockmap' = extendBlockEnv blockmap block_id regsLiveOnEntry
698 instrs2 = livenessForward regsLiveOnEntry instrs1
700 output = BasicBlock block_id instrs2
702 in ( blockmap', output)
704 -- | Calculate liveness going forwards,
705 -- filling in when regs are born
709 => RegSet -- regs live on this instr
710 -> [LiveInstr instr] -> [LiveInstr instr]
712 livenessForward _ [] = []
713 livenessForward rsLiveEntry (li@(Instr instr mLive) : lis)
715 = li : livenessForward rsLiveEntry lis
718 , RU _ written <- regUsageOfInstr instr
720 -- Regs that are written to but weren't live on entry to this instruction
721 -- are recorded as being born here.
723 $ filter (\r -> not $ elementOfUniqSet r rsLiveEntry) written
725 rsLiveNext = (rsLiveEntry `unionUniqSets` rsBorn)
726 `minusUniqSet` (liveDieRead live)
727 `minusUniqSet` (liveDieWrite live)
729 in Instr instr (Just live { liveBorn = rsBorn })
730 : livenessForward rsLiveNext lis
732 livenessForward _ _ = panic "RegLiveness.livenessForward: no match"
735 -- | Calculate liveness going backwards,
736 -- filling in when regs die, and what regs are live across each instruction
740 => RegSet -- regs live on this instr
741 -> BlockMap RegSet -- regs live on entry to other BBs
742 -> [LiveInstr instr] -- instructions (accum)
743 -> [instr] -- instructions
744 -> (RegSet, [LiveInstr instr])
746 livenessBack liveregs _ done [] = (liveregs, done)
748 livenessBack liveregs blockmap acc (instr : instrs)
749 = let (liveregs', instr') = liveness1 liveregs blockmap instr
750 in livenessBack liveregs' blockmap (instr' : acc) instrs
753 -- don't bother tagging comments or deltas with liveness
759 -> (RegSet, LiveInstr instr)
761 liveness1 liveregs _ instr
763 = (liveregs, Instr instr Nothing)
765 liveness1 liveregs blockmap instr
768 = (liveregs1, Instr instr
770 { liveBorn = emptyUniqSet
771 , liveDieRead = mkUniqSet r_dying
772 , liveDieWrite = mkUniqSet w_dying }))
775 = (liveregs_br, Instr instr
777 { liveBorn = emptyUniqSet
778 , liveDieRead = mkUniqSet r_dying_br
779 , liveDieWrite = mkUniqSet w_dying }))
782 RU read written = regUsageOfInstr instr
784 -- registers that were written here are dead going backwards.
785 -- registers that were read here are live going backwards.
786 liveregs1 = (liveregs `delListFromUniqSet` written)
787 `addListToUniqSet` read
789 -- registers that are not live beyond this point, are recorded
791 r_dying = [ reg | reg <- read, reg `notElem` written,
792 not (elementOfUniqSet reg liveregs) ]
794 w_dying = [ reg | reg <- written,
795 not (elementOfUniqSet reg liveregs) ]
797 -- union in the live regs from all the jump destinations of this
799 targets = jumpDestsOfInstr instr -- where we go from here
800 not_a_branch = null targets
802 targetLiveRegs target
803 = case lookupBlockEnv blockmap target of
805 Nothing -> emptyRegMap
807 live_from_branch = unionManyUniqSets (map targetLiveRegs targets)
809 liveregs_br = liveregs1 `unionUniqSets` live_from_branch
811 -- registers that are live only in the branch targets should
812 -- be listed as dying here.
813 live_branch_only = live_from_branch `minusUniqSet` liveregs
814 r_dying_br = uniqSetToList (mkUniqSet r_dying `unionUniqSets`