NCG: Refactor representation of code with liveness info
[ghc-hetmet.git] / compiler / nativeGen / RegAlloc / Liveness.hs
1 -----------------------------------------------------------------------------
2 --
3 -- The register liveness determinator
4 --
5 -- (c) The University of Glasgow 2004
6 --
7 -----------------------------------------------------------------------------
8 {-# OPTIONS -Wall -fno-warn-name-shadowing #-}
9
10 module RegAlloc.Liveness (
11         RegSet,
12         RegMap, emptyRegMap,
13         BlockMap, emptyBlockMap,
14         LiveCmmTop,
15         InstrSR   (..),
16         LiveInstr (..),
17         Liveness (..),
18         LiveInfo (..),
19         LiveBasicBlock,
20
21         mapBlockTop,    mapBlockTopM,
22         mapGenBlockTop, mapGenBlockTopM,
23         stripLive,
24         stripLiveBlock,
25         slurpConflicts,
26         slurpReloadCoalesce,
27         eraseDeltasLive,
28         patchEraseLive,
29         patchRegsLiveInstr,
30         regLiveness,
31         natCmmTopToLive
32   ) where
33
34
35 import Reg
36 import Instruction
37
38 import BlockId
39 import Cmm hiding (RegSet)
40 import PprCmm()
41
42 import Digraph
43 import Outputable
44 import Unique
45 import UniqSet
46 import UniqFM
47 import UniqSupply
48 import Bag
49 import State
50 import FastString
51
52 import Data.List
53 import Data.Maybe
54
55 -----------------------------------------------------------------------------
56 type RegSet = UniqSet Reg
57
58 type RegMap a = UniqFM a
59
60 emptyRegMap :: UniqFM a
61 emptyRegMap = emptyUFM
62
63 type BlockMap a = BlockEnv a
64
65 emptyBlockMap :: BlockEnv a
66 emptyBlockMap = emptyBlockEnv
67
68
69 -- | A top level thing which carries liveness information.
70 type LiveCmmTop instr
71         = GenCmmTop
72                 CmmStatic
73                 LiveInfo
74                 [SCC (LiveBasicBlock instr)]
75
76
77 -- | The register allocator also wants to use SPILL/RELOAD meta instructions,
78 --      so we'll keep those here.
79 data InstrSR instr
80         -- | A real machine instruction
81         = Instr  instr
82
83         -- | spill this reg to a stack slot
84         | SPILL  Reg Int
85
86         -- | reload this reg from a stack slot
87         | RELOAD Int Reg
88
89 instance Instruction instr => Instruction (InstrSR instr) where
90         regUsageOfInstr i
91          = case i of
92                 Instr  instr    -> regUsageOfInstr instr
93                 SPILL  reg _    -> RU [reg] []
94                 RELOAD _ reg    -> RU [] [reg]
95
96         patchRegsOfInstr i f
97          = case i of
98                 Instr instr     -> Instr (patchRegsOfInstr instr f)
99                 SPILL  reg slot -> SPILL (f reg) slot
100                 RELOAD slot reg -> RELOAD slot (f reg)
101
102         isJumpishInstr i
103          = case i of
104                 Instr instr     -> isJumpishInstr instr
105                 _               -> False
106
107         jumpDestsOfInstr i
108          = case i of
109                 Instr instr     -> jumpDestsOfInstr instr 
110                 _               -> []
111
112         patchJumpInstr i f
113          = case i of
114                 Instr instr     -> Instr (patchJumpInstr instr f)
115                 _               -> i
116
117         mkSpillInstr            = error "mkSpillInstr[InstrSR]: Not making SPILL meta-instr"
118         mkLoadInstr             = error "mkLoadInstr[InstrSR]: Not making LOAD meta-instr"
119
120         takeDeltaInstr i
121          = case i of
122                 Instr instr     -> takeDeltaInstr instr
123                 _               -> Nothing
124
125         isMetaInstr i
126          = case i of
127                 Instr instr     -> isMetaInstr instr
128                 _               -> False
129
130         mkRegRegMoveInstr r1 r2 = Instr (mkRegRegMoveInstr r1 r2)
131
132         takeRegRegMoveInstr i
133          = case i of
134                 Instr instr     -> takeRegRegMoveInstr instr
135                 _               -> Nothing
136
137         mkJumpInstr target      = map Instr (mkJumpInstr target)
138                 
139
140
141 -- | An instruction with liveness information.
142 data LiveInstr instr
143         = LiveInstr (InstrSR instr) (Maybe Liveness)
144         
145
146
147 -- | Liveness information.
148 --      The regs which die are ones which are no longer live in the *next* instruction
149 --      in this sequence.
150 --      (NB. if the instruction is a jump, these registers might still be live
151 --      at the jump target(s) - you have to check the liveness at the destination
152 --      block to find out).
153
154 data Liveness
155         = Liveness
156         { liveBorn      :: RegSet       -- ^ registers born in this instruction (written to for first time).
157         , liveDieRead   :: RegSet       -- ^ registers that died because they were read for the last time.
158         , liveDieWrite  :: RegSet }     -- ^ registers that died because they were clobbered by something.
159
160
161 -- | Stash regs live on entry to each basic block in the info part of the cmm code.
162 data LiveInfo
163         = LiveInfo
164                 [CmmStatic]                     -- cmm static stuff
165                 (Maybe BlockId)                 -- id of the first block
166                 (Maybe (BlockMap RegSet))       -- argument locals live on entry to this block
167
168 -- | A basic block with liveness information.
169 type LiveBasicBlock instr
170         = GenBasicBlock (LiveInstr instr)
171
172
173 instance Outputable instr
174       => Outputable (InstrSR instr) where
175
176         ppr (Instr realInstr)
177            = ppr realInstr
178
179         ppr (SPILL reg slot)
180            = hcat [
181                 ptext (sLit "\tSPILL"),
182                 char ' ',
183                 ppr reg,
184                 comma,
185                 ptext (sLit "SLOT") <> parens (int slot)]
186
187         ppr (RELOAD slot reg)
188            = hcat [
189                 ptext (sLit "\tRELOAD"),
190                 char ' ',
191                 ptext (sLit "SLOT") <> parens (int slot),
192                 comma,
193                 ppr reg]
194
195 instance Outputable instr 
196       => Outputable (LiveInstr instr) where
197
198         ppr (LiveInstr instr Nothing)
199          = ppr instr
200
201         ppr (LiveInstr instr (Just live))
202          =  ppr instr
203                 $$ (nest 8
204                         $ vcat
205                         [ pprRegs (ptext (sLit "# born:    ")) (liveBorn live)
206                         , pprRegs (ptext (sLit "# r_dying: ")) (liveDieRead live)
207                         , pprRegs (ptext (sLit "# w_dying: ")) (liveDieWrite live) ]
208                     $+$ space)
209
210          where  pprRegs :: SDoc -> RegSet -> SDoc
211                 pprRegs name regs
212                  | isEmptyUniqSet regs  = empty
213                  | otherwise            = name <> (hcat $ punctuate space $ map ppr $ uniqSetToList regs)
214
215 instance Outputable LiveInfo where
216         ppr (LiveInfo static firstId liveOnEntry)
217                 =  (vcat $ map ppr static)
218                 $$ text "# firstId     = " <> ppr firstId
219                 $$ text "# liveOnEntry = " <> ppr liveOnEntry
220
221
222
223 -- | map a function across all the basic blocks in this code
224 --
225 mapBlockTop
226         :: (LiveBasicBlock instr -> LiveBasicBlock instr)
227         -> LiveCmmTop instr -> LiveCmmTop instr
228
229 mapBlockTop f cmm
230         = evalState (mapBlockTopM (\x -> return $ f x) cmm) ()
231
232
233 -- | map a function across all the basic blocks in this code (monadic version)
234 --
235 mapBlockTopM
236         :: Monad m
237         => (LiveBasicBlock instr -> m (LiveBasicBlock instr))
238         -> LiveCmmTop instr -> m (LiveCmmTop instr)
239
240 mapBlockTopM _ cmm@(CmmData{})
241         = return cmm
242
243 mapBlockTopM f (CmmProc header label params sccs)
244  = do   sccs'   <- mapM (mapSCCM f) sccs
245         return  $ CmmProc header label params sccs'
246
247 mapSCCM :: Monad m => (a -> m b) -> SCC a -> m (SCC b)
248 mapSCCM f (AcyclicSCC x)        
249  = do   x'      <- f x
250         return  $ AcyclicSCC x'
251
252 mapSCCM f (CyclicSCC xs)
253  = do   xs'     <- mapM f xs
254         return  $ CyclicSCC xs'
255
256
257 -- map a function across all the basic blocks in this code
258 mapGenBlockTop
259         :: (GenBasicBlock             i -> GenBasicBlock            i)
260         -> (GenCmmTop d h (ListGraph i) -> GenCmmTop d h (ListGraph i))
261
262 mapGenBlockTop f cmm
263         = evalState (mapGenBlockTopM (\x -> return $ f x) cmm) ()
264
265
266 -- | map a function across all the basic blocks in this code (monadic version)
267 mapGenBlockTopM
268         :: Monad m
269         => (GenBasicBlock            i  -> m (GenBasicBlock            i))
270         -> (GenCmmTop d h (ListGraph i) -> m (GenCmmTop d h (ListGraph i)))
271
272 mapGenBlockTopM _ cmm@(CmmData{})
273         = return cmm
274
275 mapGenBlockTopM f (CmmProc header label params (ListGraph blocks))
276  = do   blocks' <- mapM f blocks
277         return  $ CmmProc header label params (ListGraph blocks')
278
279
280 -- | Slurp out the list of register conflicts and reg-reg moves from this top level thing.
281 --      Slurping of conflicts and moves is wrapped up together so we don't have
282 --      to make two passes over the same code when we want to build the graph.
283 --
284 slurpConflicts 
285         :: Instruction instr
286         => LiveCmmTop instr 
287         -> (Bag (UniqSet Reg), Bag (Reg, Reg))
288
289 slurpConflicts live
290         = slurpCmm (emptyBag, emptyBag) live
291
292  where  slurpCmm   rs  CmmData{}                = rs
293         slurpCmm   rs (CmmProc info _ _ sccs)
294                 = foldl' (slurpSCC info) rs sccs
295
296         slurpSCC  info rs (AcyclicSCC b)        
297                 = slurpBlock info rs b
298
299         slurpSCC  info rs (CyclicSCC bs)
300                 = foldl'  (slurpBlock info) rs bs
301
302         slurpBlock info rs (BasicBlock blockId instrs)  
303                 | LiveInfo _ _ (Just blockLive) <- info
304                 , Just rsLiveEntry              <- lookupBlockEnv blockLive blockId
305                 , (conflicts, moves)            <- slurpLIs rsLiveEntry rs instrs
306                 = (consBag rsLiveEntry conflicts, moves)
307
308                 | otherwise
309                 = panic "Liveness.slurpConflicts: bad block"
310
311         slurpLIs rsLive (conflicts, moves) []
312                 = (consBag rsLive conflicts, moves)
313
314         slurpLIs rsLive rs (LiveInstr _ Nothing     : lis)      
315                 = slurpLIs rsLive rs lis
316                 
317         slurpLIs rsLiveEntry (conflicts, moves) (LiveInstr instr (Just live) : lis)
318          = let
319                 -- regs that die because they are read for the last time at the start of an instruction
320                 --      are not live across it.
321                 rsLiveAcross    = rsLiveEntry `minusUniqSet` (liveDieRead live)
322
323                 -- regs live on entry to the next instruction.
324                 --      be careful of orphans, make sure to delete dying regs _after_ unioning
325                 --      in the ones that are born here.
326                 rsLiveNext      = (rsLiveAcross `unionUniqSets` (liveBorn     live))
327                                                 `minusUniqSet`  (liveDieWrite live)
328
329                 -- orphan vregs are the ones that die in the same instruction they are born in.
330                 --      these are likely to be results that are never used, but we still
331                 --      need to assign a hreg to them..
332                 rsOrphans       = intersectUniqSets
333                                         (liveBorn live)
334                                         (unionUniqSets (liveDieWrite live) (liveDieRead live))
335
336                 --
337                 rsConflicts     = unionUniqSets rsLiveNext rsOrphans
338
339           in    case takeRegRegMoveInstr instr of
340                  Just rr        -> slurpLIs rsLiveNext
341                                         ( consBag rsConflicts conflicts
342                                         , consBag rr moves) lis
343
344                  Nothing        -> slurpLIs rsLiveNext
345                                         ( consBag rsConflicts conflicts
346                                         , moves) lis
347
348
349 -- | For spill\/reloads
350 --
351 --      SPILL  v1, slot1
352 --      ...
353 --      RELOAD slot1, v2
354 --
355 --      If we can arrange that v1 and v2 are allocated to the same hreg it's more likely
356 --      the spill\/reload instrs can be cleaned and replaced by a nop reg-reg move.
357 --
358 --
359 slurpReloadCoalesce 
360         :: Instruction instr
361         => LiveCmmTop instr
362         -> Bag (Reg, Reg)
363
364 slurpReloadCoalesce live
365         = slurpCmm emptyBag live
366
367  where  slurpCmm cs CmmData{}   = cs
368         slurpCmm cs (CmmProc _ _ _ sccs)
369                 = slurpComp cs (flattenSCCs sccs)
370
371         slurpComp  cs blocks
372          = let  (moveBags, _)   = runState (slurpCompM blocks) emptyUFM
373            in   unionManyBags (cs : moveBags)
374
375         slurpCompM blocks
376          = do   -- run the analysis once to record the mapping across jumps.
377                 mapM_   (slurpBlock False) blocks
378
379                 -- run it a second time while using the information from the last pass.
380                 --      We /could/ run this many more times to deal with graphical control
381                 --      flow and propagating info across multiple jumps, but it's probably
382                 --      not worth the trouble.
383                 mapM    (slurpBlock True) blocks
384
385         slurpBlock propagate (BasicBlock blockId instrs)
386          = do   -- grab the slot map for entry to this block
387                 slotMap         <- if propagate
388                                         then getSlotMap blockId
389                                         else return emptyUFM
390
391                 (_, mMoves)     <- mapAccumLM slurpLI slotMap instrs
392                 return $ listToBag $ catMaybes mMoves
393
394         slurpLI :: Instruction instr
395                 => UniqFM Reg                           -- current slotMap
396                 -> LiveInstr instr
397                 -> State (UniqFM [UniqFM Reg])          -- blockId -> [slot -> reg]
398                                                         --      for tracking slotMaps across jumps
399
400                          ( UniqFM Reg                   -- new slotMap
401                          , Maybe (Reg, Reg))            -- maybe a new coalesce edge
402
403         slurpLI slotMap li
404
405                 -- remember what reg was stored into the slot
406                 | LiveInstr (SPILL reg slot) _  <- li
407                 , slotMap'                      <- addToUFM slotMap slot reg
408                 = return (slotMap', Nothing)
409
410                 -- add an edge betwen the this reg and the last one stored into the slot
411                 | LiveInstr (RELOAD slot reg) _ <- li
412                 = case lookupUFM slotMap slot of
413                         Just reg2
414                          | reg /= reg2  -> return (slotMap, Just (reg, reg2))
415                          | otherwise    -> return (slotMap, Nothing)
416
417                         Nothing         -> return (slotMap, Nothing)
418
419                 -- if we hit a jump, remember the current slotMap
420                 | LiveInstr (Instr instr) _     <- li
421                 , targets                       <- jumpDestsOfInstr instr
422                 , not $ null targets
423                 = do    mapM_   (accSlotMap slotMap) targets
424                         return  (slotMap, Nothing)
425
426                 | otherwise
427                 = return (slotMap, Nothing)
428
429         -- record a slotmap for an in edge to this block
430         accSlotMap slotMap blockId
431                 = modify (\s -> addToUFM_C (++) s blockId [slotMap])
432
433         -- work out the slot map on entry to this block
434         --      if we have slot maps for multiple in-edges then we need to merge them.
435         getSlotMap blockId
436          = do   map             <- get
437                 let slotMaps    = fromMaybe [] (lookupUFM map blockId)
438                 return          $ foldr mergeSlotMaps emptyUFM slotMaps
439
440         mergeSlotMaps :: UniqFM Reg -> UniqFM Reg -> UniqFM Reg
441         mergeSlotMaps map1 map2
442                 = listToUFM
443                 $ [ (k, r1)     | (k, r1)       <- ufmToList map1
444                                 , case lookupUFM map2 k of
445                                         Nothing -> False
446                                         Just r2 -> r1 == r2 ]
447
448
449 -- | Strip away liveness information, yielding NatCmmTop
450
451 stripLive 
452         :: Instruction instr
453         => LiveCmmTop instr 
454         -> NatCmmTop instr
455
456 stripLive live
457         = stripCmm live
458
459  where  stripCmm (CmmData sec ds)       = CmmData sec ds
460         stripCmm (CmmProc (LiveInfo info _ _) label params sccs)
461                 = CmmProc info label params
462                           (ListGraph $ map stripLiveBlock $ flattenSCCs sccs)
463         
464
465 -- | Strip away liveness information from a basic block,
466 --      and make real spill instructions out of SPILL, RELOAD pseudos along the way.
467
468 stripLiveBlock
469         :: Instruction instr
470         => LiveBasicBlock instr
471         -> NatBasicBlock instr
472
473 stripLiveBlock (BasicBlock i lis)
474  =      BasicBlock i instrs'
475
476  where  (instrs', _)
477                 = runState (spillNat [] lis) 0
478
479         spillNat acc []
480          =      return (reverse acc)
481
482         spillNat acc (LiveInstr (SPILL reg slot) _ : instrs)
483          = do   delta   <- get
484                 spillNat (mkSpillInstr reg delta slot : acc) instrs
485
486         spillNat acc (LiveInstr (RELOAD slot reg) _ : instrs)
487          = do   delta   <- get
488                 spillNat (mkLoadInstr reg delta slot : acc) instrs
489
490         spillNat acc (LiveInstr (Instr instr) _ : instrs)
491          | Just i <- takeDeltaInstr instr
492          = do   put i
493                 spillNat acc instrs
494
495         spillNat acc (LiveInstr (Instr instr) _ : instrs)
496          =      spillNat (instr : acc) instrs
497
498
499 -- | Erase Delta instructions.
500
501 eraseDeltasLive 
502         :: Instruction instr
503         => LiveCmmTop instr
504         -> LiveCmmTop instr
505
506 eraseDeltasLive cmm
507         = mapBlockTop eraseBlock cmm
508  where
509         eraseBlock (BasicBlock id lis)
510                 = BasicBlock id
511                 $ filter (\(LiveInstr i _) -> not $ isJust $ takeDeltaInstr i)
512                 $ lis
513
514
515 -- | Patch the registers in this code according to this register mapping.
516 --      also erase reg -> reg moves when the reg is the same.
517 --      also erase reg -> reg moves when the destination dies in this instr.
518
519 patchEraseLive
520         :: Instruction instr
521         => (Reg -> Reg)
522         -> LiveCmmTop instr -> LiveCmmTop instr
523
524 patchEraseLive patchF cmm
525         = patchCmm cmm
526  where
527         patchCmm cmm@CmmData{}  = cmm
528
529         patchCmm (CmmProc info label params sccs)
530          | LiveInfo static id (Just blockMap)   <- info
531          = let  
532                 patchRegSet set = mkUniqSet $ map patchF $ uniqSetToList set
533                 blockMap'       = mapBlockEnv patchRegSet blockMap
534
535                 info'           = LiveInfo static id (Just blockMap')
536            in   CmmProc info' label params $ map patchSCC sccs
537
538          | otherwise
539          = panic "RegAlloc.Liveness.patchEraseLive: no blockMap"
540
541         patchSCC (AcyclicSCC b)  = AcyclicSCC (patchBlock b)
542         patchSCC (CyclicSCC  bs) = CyclicSCC  (map patchBlock bs)
543
544         patchBlock (BasicBlock id lis)
545                 = BasicBlock id $ patchInstrs lis
546
547         patchInstrs []          = []
548         patchInstrs (li : lis)
549
550                 | LiveInstr i (Just live)       <- li'
551                 , Just (r1, r2) <- takeRegRegMoveInstr i
552                 , eatMe r1 r2 live
553                 = patchInstrs lis
554
555                 | otherwise
556                 = li' : patchInstrs lis
557
558                 where   li'     = patchRegsLiveInstr patchF li
559
560         eatMe   r1 r2 live
561                 -- source and destination regs are the same
562                 | r1 == r2      = True
563
564                 -- desination reg is never used
565                 | elementOfUniqSet r2 (liveBorn live)
566                 , elementOfUniqSet r2 (liveDieRead live) || elementOfUniqSet r2 (liveDieWrite live)
567                 = True
568
569                 | otherwise     = False
570
571
572 -- | Patch registers in this LiveInstr, including the liveness information.
573 --
574 patchRegsLiveInstr
575         :: Instruction instr
576         => (Reg -> Reg)
577         -> LiveInstr instr -> LiveInstr instr
578
579 patchRegsLiveInstr patchF li
580  = case li of
581         LiveInstr instr Nothing
582          -> LiveInstr (patchRegsOfInstr instr patchF) Nothing
583
584         LiveInstr instr (Just live)
585          -> LiveInstr
586                 (patchRegsOfInstr instr patchF)
587                 (Just live
588                         { -- WARNING: have to go via lists here because patchF changes the uniq in the Reg
589                           liveBorn      = mkUniqSet $ map patchF $ uniqSetToList $ liveBorn live
590                         , liveDieRead   = mkUniqSet $ map patchF $ uniqSetToList $ liveDieRead live
591                         , liveDieWrite  = mkUniqSet $ map patchF $ uniqSetToList $ liveDieWrite live })
592
593
594 --------------------------------------------------------------------------------
595 -- | Convert a NatCmmTop to a LiveCmmTop, with empty liveness information
596
597 natCmmTopToLive 
598         :: Instruction instr
599         => NatCmmTop instr
600         -> LiveCmmTop instr
601
602 natCmmTopToLive (CmmData i d)
603         = CmmData i d
604
605 natCmmTopToLive (CmmProc info lbl params (ListGraph []))
606         = CmmProc (LiveInfo info Nothing Nothing)
607                   lbl params []
608
609 natCmmTopToLive (CmmProc info lbl params (ListGraph blocks@(first : _)))
610  = let  first_id        = blockId first
611         sccs            = sccBlocks blocks
612         sccsLive        = map (fmap (\(BasicBlock l instrs) -> 
613                                         BasicBlock l (map (\i -> LiveInstr (Instr i) Nothing) instrs)))
614                         $ sccs
615                                 
616    in   CmmProc (LiveInfo info (Just first_id) Nothing)
617                 lbl params sccsLive
618
619
620 sccBlocks 
621         :: Instruction instr
622         => [NatBasicBlock instr] 
623         -> [SCC (NatBasicBlock instr)]
624
625 sccBlocks blocks = stronglyConnCompFromEdgedVertices graph
626   where
627         getOutEdges :: Instruction instr => [instr] -> [BlockId]
628         getOutEdges instrs = concat $ map jumpDestsOfInstr instrs
629
630         graph = [ (block, getUnique id, map getUnique (getOutEdges instrs))
631                 | block@(BasicBlock id instrs) <- blocks ]
632
633
634 ---------------------------------------------------------------------------------
635 -- Annotate code with register liveness information
636 --
637 regLiveness
638         :: Instruction instr
639         => LiveCmmTop instr
640         -> UniqSM (LiveCmmTop instr)
641
642 regLiveness (CmmData i d)
643         = returnUs $ CmmData i d
644
645 regLiveness (CmmProc info lbl params [])
646         | LiveInfo static mFirst _      <- info
647         = returnUs $ CmmProc
648                         (LiveInfo static mFirst (Just emptyBlockEnv))
649                         lbl params []
650
651 regLiveness (CmmProc info lbl params sccs)
652         | LiveInfo static mFirst _      <- info
653         = let   (ann_sccs, block_live)  = computeLiveness sccs
654
655           in    returnUs $ CmmProc (LiveInfo static mFirst (Just block_live))
656                            lbl params ann_sccs
657
658
659
660 -- -----------------------------------------------------------------------------
661 -- Computing liveness
662
663 computeLiveness
664         :: Instruction instr
665         => [SCC (LiveBasicBlock instr)]
666         -> ([SCC (LiveBasicBlock instr)],       -- instructions annotated with list of registers
667                                                 -- which are "dead after this instruction".
668                BlockMap RegSet)                 -- blocks annontated with set of live registers
669                                                 -- on entry to the block.
670         
671   -- NOTE: on entry, the SCCs are in "reverse" order: later blocks may transfer
672   -- control to earlier ones only.  The SCCs returned are in the *opposite* 
673   -- order, which is exactly what we want for the next pass.
674
675 computeLiveness sccs
676         = livenessSCCs emptyBlockMap [] sccs
677
678
679 livenessSCCs
680        :: Instruction instr
681        => BlockMap RegSet
682        -> [SCC (LiveBasicBlock instr)]          -- accum
683        -> [SCC (LiveBasicBlock instr)]
684        -> ( [SCC (LiveBasicBlock instr)]
685           , BlockMap RegSet)
686
687 livenessSCCs blockmap done [] 
688         = (done, blockmap)
689
690 livenessSCCs blockmap done (AcyclicSCC block : sccs)
691  = let  (blockmap', block')     = livenessBlock blockmap block
692    in   livenessSCCs blockmap' (AcyclicSCC block' : done) sccs
693
694 livenessSCCs blockmap done
695         (CyclicSCC blocks : sccs) =
696         livenessSCCs blockmap' (CyclicSCC blocks':done) sccs
697  where      (blockmap', blocks')
698                 = iterateUntilUnchanged linearLiveness equalBlockMaps
699                                       blockmap blocks
700
701             iterateUntilUnchanged
702                 :: (a -> b -> (a,c)) -> (a -> a -> Bool)
703                 -> a -> b
704                 -> (a,c)
705
706             iterateUntilUnchanged f eq a b
707                 = head $
708                   concatMap tail $
709                   groupBy (\(a1, _) (a2, _) -> eq a1 a2) $
710                   iterate (\(a, _) -> f a b) $
711                   (a, panic "RegLiveness.livenessSCCs")
712
713
714             linearLiveness 
715                 :: Instruction instr
716                 => BlockMap RegSet -> [LiveBasicBlock instr]
717                 -> (BlockMap RegSet, [LiveBasicBlock instr])
718
719             linearLiveness = mapAccumL livenessBlock
720
721                 -- probably the least efficient way to compare two
722                 -- BlockMaps for equality.
723             equalBlockMaps a b
724                 = a' == b'
725               where a' = map f $ blockEnvToList a
726                     b' = map f $ blockEnvToList b
727                     f (key,elt) = (key, uniqSetToList elt)
728
729
730
731 -- | Annotate a basic block with register liveness information.
732 --
733 livenessBlock
734         :: Instruction instr
735         => BlockMap RegSet
736         -> LiveBasicBlock instr
737         -> (BlockMap RegSet, LiveBasicBlock instr)
738
739 livenessBlock blockmap (BasicBlock block_id instrs)
740  = let
741         (regsLiveOnEntry, instrs1)
742                 = livenessBack emptyUniqSet blockmap [] (reverse instrs)
743         blockmap'       = extendBlockEnv blockmap block_id regsLiveOnEntry
744
745         instrs2         = livenessForward regsLiveOnEntry instrs1
746
747         output          = BasicBlock block_id instrs2
748
749    in   ( blockmap', output)
750
751 -- | Calculate liveness going forwards,
752 --      filling in when regs are born
753
754 livenessForward
755         :: Instruction instr
756         => RegSet                       -- regs live on this instr
757         -> [LiveInstr instr] -> [LiveInstr instr]
758
759 livenessForward _           []  = []
760 livenessForward rsLiveEntry (li@(LiveInstr instr mLive) : lis)
761         | Nothing               <- mLive
762         = li : livenessForward rsLiveEntry lis
763
764         | Just live     <- mLive
765         , RU _ written  <- regUsageOfInstr instr
766         = let
767                 -- Regs that are written to but weren't live on entry to this instruction
768                 --      are recorded as being born here.
769                 rsBorn          = mkUniqSet
770                                 $ filter (\r -> not $ elementOfUniqSet r rsLiveEntry) written
771
772                 rsLiveNext      = (rsLiveEntry `unionUniqSets` rsBorn)
773                                         `minusUniqSet` (liveDieRead live)
774                                         `minusUniqSet` (liveDieWrite live)
775
776         in LiveInstr instr (Just live { liveBorn = rsBorn })
777                 : livenessForward rsLiveNext lis
778
779 livenessForward _ _             = panic "RegLiveness.livenessForward: no match"
780
781
782 -- | Calculate liveness going backwards,
783 --      filling in when regs die, and what regs are live across each instruction
784
785 livenessBack
786         :: Instruction instr 
787         => RegSet                       -- regs live on this instr
788         -> BlockMap RegSet              -- regs live on entry to other BBs
789         -> [LiveInstr instr]            -- instructions (accum)
790         -> [LiveInstr instr]            -- instructions
791         -> (RegSet, [LiveInstr instr])
792
793 livenessBack liveregs _        done []  = (liveregs, done)
794
795 livenessBack liveregs blockmap acc (instr : instrs)
796  = let  (liveregs', instr')     = liveness1 liveregs blockmap instr
797    in   livenessBack liveregs' blockmap (instr' : acc) instrs
798
799
800 -- don't bother tagging comments or deltas with liveness
801 liveness1 
802         :: Instruction instr
803         => RegSet 
804         -> BlockMap RegSet 
805         -> LiveInstr instr
806         -> (RegSet, LiveInstr instr)
807
808 liveness1 liveregs _ (LiveInstr instr _)
809         | isMetaInstr instr
810         = (liveregs, LiveInstr instr Nothing)
811
812 liveness1 liveregs blockmap (LiveInstr instr _)
813
814         | not_a_branch
815         = (liveregs1, LiveInstr instr
816                         (Just $ Liveness
817                         { liveBorn      = emptyUniqSet
818                         , liveDieRead   = mkUniqSet r_dying
819                         , liveDieWrite  = mkUniqSet w_dying }))
820
821         | otherwise
822         = (liveregs_br, LiveInstr instr
823                         (Just $ Liveness
824                         { liveBorn      = emptyUniqSet
825                         , liveDieRead   = mkUniqSet r_dying_br
826                         , liveDieWrite  = mkUniqSet w_dying }))
827
828         where
829             RU read written = regUsageOfInstr instr
830
831             -- registers that were written here are dead going backwards.
832             -- registers that were read here are live going backwards.
833             liveregs1   = (liveregs `delListFromUniqSet` written)
834                                     `addListToUniqSet` read
835
836             -- registers that are not live beyond this point, are recorded
837             --  as dying here.
838             r_dying     = [ reg | reg <- read, reg `notElem` written,
839                               not (elementOfUniqSet reg liveregs) ]
840
841             w_dying     = [ reg | reg <- written,
842                              not (elementOfUniqSet reg liveregs) ]
843
844             -- union in the live regs from all the jump destinations of this
845             -- instruction.
846             targets      = jumpDestsOfInstr instr -- where we go from here
847             not_a_branch = null targets
848
849             targetLiveRegs target
850                   = case lookupBlockEnv blockmap target of
851                                 Just ra -> ra
852                                 Nothing -> emptyRegMap
853
854             live_from_branch = unionManyUniqSets (map targetLiveRegs targets)
855
856             liveregs_br = liveregs1 `unionUniqSets` live_from_branch
857
858             -- registers that are live only in the branch targets should
859             -- be listed as dying here.
860             live_branch_only = live_from_branch `minusUniqSet` liveregs
861             r_dying_br  = uniqSetToList (mkUniqSet r_dying `unionUniqSets`
862                                         live_branch_only)
863
864