1 -----------------------------------------------------------------------------
3 -- The register allocator
5 -- (c) The University of Glasgow 2004
7 -----------------------------------------------------------------------------
10 The algorithm is roughly:
12 1) Compute strongly connected components of the basic block list.
14 2) Compute liveness (mapping from pseudo register to
17 3) Walk instructions in each basic block. We keep track of
18 (a) Free real registers (a bitmap?)
19 (b) Current assignment of temporaries to machine registers and/or
20 spill slots (call this the "assignment").
21 (c) Partial mapping from basic block ids to a virt-to-loc mapping.
22 When we first encounter a branch to a basic block,
23 we fill in its entry in this table with the current mapping.
26 (a) For each real register clobbered by this instruction:
27 If a temporary resides in it,
28 If the temporary is live after this instruction,
29 Move the temporary to another (non-clobbered & free) reg,
30 or spill it to memory. Mark the temporary as residing
31 in both memory and a register if it was spilled (it might
32 need to be read by this instruction).
33 (ToDo: this is wrong for jump instructions?)
35 (b) For each temporary *read* by the instruction:
36 If the temporary does not have a real register allocation:
37 - Allocate a real register from the free list. If
39 - Find a temporary to spill. Pick one that is
40 not used in this instruction (ToDo: not
42 - generate a spill instruction
43 - If the temporary was previously spilled,
44 generate an instruction to read the temp from its spill loc.
45 (optimisation: if we can see that a real register is going to
46 be used soon, then don't use it for allocation).
48 (c) Update the current assignment
50 (d) If the intstruction is a branch:
51 if the destination block already has a register assignment,
52 Generate a new block with fixup code and redirect the
53 jump to the new block.
55 Update the block id->assignment mapping with the current
58 (e) Delete all register assignments for temps which are read
59 (only) and die here. Update the free register list.
61 (f) Mark all registers clobbered by this instruction as not free,
62 and mark temporaries which have been spilled due to clobbering
63 as in memory (step (a) marks then as in both mem & reg).
65 (g) For each temporary *written* by this instruction:
66 Allocate a real register as for (b), spilling something
68 - except when updating the assignment, drop any memory
69 locations that the temporary was previously in, since
70 they will be no longer valid after this instruction.
72 (h) Delete all register assignments for temps which are
73 written and die here (there should rarely be any). Update
74 the free register list.
76 (i) Rewrite the instruction with the new mapping.
78 (j) For each spilled reg known to be now dead, re-add its stack slot
83 module RegAllocLinear (
85 RegAllocStats, pprStats
88 #include "HsVersions.h"
97 import Unique ( Uniquable(getUnique), Unique )
104 import Data.Maybe ( fromJust )
106 import Data.List ( nub, partition, mapAccumL, foldl')
107 import Control.Monad ( when )
112 -- -----------------------------------------------------------------------------
113 -- The free register set
115 -- This needs to be *efficient*
117 {- Here's an inefficient 'executable specification' of the FreeRegs data type:
118 type FreeRegs = [RegNo]
121 releaseReg n f = if n `elem` f then f else (n : f)
122 initFreeRegs = allocatableRegs
123 getFreeRegs cls f = filter ( (==cls) . regClass . RealReg ) f
124 allocateReg f r = filter (/= r) f
127 #if defined(powerpc_TARGET_ARCH)
129 -- The PowerPC has 32 integer and 32 floating point registers.
130 -- This is 32bit PowerPC, so Word64 is inefficient - two Word32s are much
132 -- Note that when getFreeRegs scans for free registers, it starts at register
133 -- 31 and counts down. This is a hack for the PowerPC - the higher-numbered
134 -- registers are callee-saves, while the lower regs are caller-saves, so it
135 -- makes sense to start at the high end.
136 -- Apart from that, the code does nothing PowerPC-specific, so feel free to
137 -- add your favourite platform to the #if (if you have 64 registers but only
140 data FreeRegs = FreeRegs !Word32 !Word32
141 deriving( Show ) -- The Show is used in an ASSERT
143 noFreeRegs :: FreeRegs
144 noFreeRegs = FreeRegs 0 0
146 releaseReg :: RegNo -> FreeRegs -> FreeRegs
147 releaseReg r (FreeRegs g f)
148 | r > 31 = FreeRegs g (f .|. (1 `shiftL` (fromIntegral r - 32)))
149 | otherwise = FreeRegs (g .|. (1 `shiftL` fromIntegral r)) f
151 initFreeRegs :: FreeRegs
152 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
154 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
155 getFreeRegs cls (FreeRegs g f)
156 | RcDouble <- cls = go f (0x80000000) 63
157 | RcInteger <- cls = go g (0x80000000) 31
160 go x m i | x .&. m /= 0 = i : (go x (m `shiftR` 1) $! i-1)
161 | otherwise = go x (m `shiftR` 1) $! i-1
163 allocateReg :: RegNo -> FreeRegs -> FreeRegs
164 allocateReg r (FreeRegs g f)
165 | r > 31 = FreeRegs g (f .&. complement (1 `shiftL` (fromIntegral r - 32)))
166 | otherwise = FreeRegs (g .&. complement (1 `shiftL` fromIntegral r)) f
170 -- If we have less than 32 registers, or if we have efficient 64-bit words,
171 -- we will just use a single bitfield.
173 #if defined(alpha_TARGET_ARCH)
174 type FreeRegs = Word64
176 type FreeRegs = Word32
179 noFreeRegs :: FreeRegs
182 releaseReg :: RegNo -> FreeRegs -> FreeRegs
183 releaseReg n f = f .|. (1 `shiftL` n)
185 initFreeRegs :: FreeRegs
186 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
188 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
189 getFreeRegs cls f = go f 0
192 | n .&. 1 /= 0 && regClass (RealReg m) == cls
193 = m : (go (n `shiftR` 1) $! (m+1))
195 = go (n `shiftR` 1) $! (m+1)
196 -- ToDo: there's no point looking through all the integer registers
197 -- in order to find a floating-point one.
199 allocateReg :: RegNo -> FreeRegs -> FreeRegs
200 allocateReg r f = f .&. complement (1 `shiftL` fromIntegral r)
204 -- -----------------------------------------------------------------------------
205 -- The assignment of virtual registers to stack slots
207 -- We have lots of stack slots. Memory-to-memory moves are a pain on most
208 -- architectures. Therefore, we avoid having to generate memory-to-memory moves
209 -- by simply giving every virtual register its own stack slot.
211 -- The StackMap stack map keeps track of virtual register - stack slot
212 -- associations and of which stack slots are still free. Once it has been
213 -- associated, a stack slot is never "freed" or removed from the StackMap again,
214 -- it remains associated until we are done with the current CmmProc.
217 data StackMap = StackMap [StackSlot] (UniqFM StackSlot)
219 emptyStackMap :: StackMap
220 emptyStackMap = StackMap [0..maxSpillSlots] emptyUFM
222 getStackSlotFor :: StackMap -> Unique -> (StackMap,Int)
223 getStackSlotFor fs@(StackMap [] reserved) reg
224 = panic "RegAllocLinear.getStackSlotFor: out of stack slots"
225 getStackSlotFor fs@(StackMap (freeSlot:stack') reserved) reg =
226 case lookupUFM reserved reg of
227 Just slot -> (fs,slot)
228 Nothing -> (StackMap stack' (addToUFM reserved reg freeSlot), freeSlot)
230 -- -----------------------------------------------------------------------------
231 -- Top level of the register allocator
233 -- Allocate registers
236 -> UniqSM (NatCmmTop, Maybe RegAllocStats)
238 regAlloc cmm@(CmmData sec d)
243 regAlloc cmm@(CmmProc (LiveInfo info _ _) lbl params [])
245 ( CmmProc info lbl params []
248 regAlloc cmm@(CmmProc static lbl params comps)
249 | LiveInfo info (Just first_id) block_live <- static
251 -- do register allocation on each component.
252 (final_blocks, stats)
253 <- linearRegAlloc block_live
254 $ map (\b -> case b of
255 BasicBlock i [b] -> AcyclicSCC b
256 BasicBlock i bs -> CyclicSCC bs)
259 -- make sure the block that was first in the input list
260 -- stays at the front of the output
261 let ((first':_), rest')
262 = partition ((== first_id) . blockId) final_blocks
264 return ( CmmProc info lbl params (first' : rest')
269 -- -----------------------------------------------------------------------------
270 -- Linear sweep to allocate registers
272 data Loc = InReg {-# UNPACK #-} !RegNo
273 | InMem {-# UNPACK #-} !Int -- stack slot
274 | InBoth {-# UNPACK #-} !RegNo
275 {-# UNPACK #-} !Int -- stack slot
276 deriving (Eq, Show, Ord)
279 A temporary can be marked as living in both a register and memory
280 (InBoth), for example if it was recently loaded from a spill location.
281 This makes it cheap to spill (no save instruction required), but we
282 have to be careful to turn this into InReg if the value in the
285 This is also useful when a temporary is about to be clobbered. We
286 save it in a spill location, but mark it as InBoth because the current
287 instruction might still want to read it.
291 instance Outputable Loc where
292 ppr l = text (show l)
296 -- | Do register allocation on some basic blocks.
299 :: BlockMap RegSet -- ^ live regs on entry to each basic block
300 -> [SCC LiveBasicBlock] -- ^ instructions annotated with "deaths"
301 -> UniqSM ([NatBasicBlock], RegAllocStats)
303 linearRegAlloc block_live sccs
305 let (block_assig', stackMap', stats, blocks) =
306 runR emptyBlockMap initFreeRegs emptyRegMap emptyStackMap us
307 $ linearRA_SCCs block_live [] sccs
309 return (blocks, stats)
311 linearRA_SCCs block_live blocksAcc []
312 = return $ reverse blocksAcc
314 linearRA_SCCs block_live blocksAcc (AcyclicSCC block : sccs)
315 = do blocks' <- processBlock block_live block
316 linearRA_SCCs block_live
317 ((reverse blocks') ++ blocksAcc)
320 linearRA_SCCs block_live blocksAcc (CyclicSCC blocks : sccs)
321 = do blockss' <- mapM (processBlock block_live) blocks
322 linearRA_SCCs block_live
323 (reverse (concat blockss') ++ blocksAcc)
327 -- | Do register allocation on this basic block
330 :: BlockMap RegSet -- ^ live regs on entry to each basic block
331 -> LiveBasicBlock -- ^ block to do register allocation on
332 -> RegM [NatBasicBlock] -- ^ block with registers allocated
334 processBlock block_live (BasicBlock id instrs)
337 <- linearRA block_live [] [] instrs
339 return $ BasicBlock id instrs' : fixups
342 -- | Load the freeregs and current reg assignment into the RegM state
343 -- for the basic block with this BlockId.
344 initBlock :: BlockId -> RegM ()
346 = do block_assig <- getBlockAssigR
347 case lookupUFM block_assig id of
348 -- no prior info about this block: assume everything is
349 -- free and the assignment is empty.
351 -> do setFreeRegsR initFreeRegs
352 setAssigR emptyRegMap
354 -- load info about register assignments leading into this block.
355 Just (freeregs, assig)
356 -> do setFreeRegsR freeregs
362 -> [Instr] -> [NatBasicBlock] -> [LiveInstr]
363 -> RegM ([Instr], [NatBasicBlock])
365 linearRA block_live instr_acc fixups []
366 = return (reverse instr_acc, fixups)
368 linearRA block_live instr_acc fixups (instr:instrs)
369 = do (instr_acc', new_fixups) <- raInsn block_live instr_acc instr
370 linearRA block_live instr_acc' (new_fixups++fixups) instrs
372 -- -----------------------------------------------------------------------------
373 -- Register allocation for a single instruction
375 type BlockAssignment = BlockMap (FreeRegs, RegMap Loc)
377 raInsn :: BlockMap RegSet -- Live temporaries at each basic block
378 -> [Instr] -- new instructions (accum.)
379 -> LiveInstr -- the instruction (with "deaths")
381 [Instr], -- new instructions
382 [NatBasicBlock] -- extra fixup blocks
385 raInsn block_live new_instrs (Instr instr@(COMMENT _) Nothing)
386 = return (new_instrs, [])
388 raInsn block_live new_instrs (Instr instr@(DELTA n) Nothing)
391 return (new_instrs, [])
393 raInsn block_live new_instrs (Instr instr (Just live))
397 -- If we have a reg->reg move between virtual registers, where the
398 -- src register is not live after this instruction, and the dst
399 -- register does not already have an assignment,
400 -- and the source register is assigned to a register, not to a spill slot,
401 -- then we can eliminate the instruction.
402 -- (we can't eliminitate it if the source register is on the stack, because
403 -- we do not want to use one spill slot for different virtual registers)
404 case isRegRegMove instr of
405 Just (src,dst) | src `elementOfUniqSet` (liveDieRead live),
407 not (dst `elemUFM` assig),
408 Just (InReg _) <- (lookupUFM assig src) -> do
410 RealReg i -> setAssigR (addToUFM assig dst (InReg i))
411 -- if src is a fixed reg, then we just map dest to this
412 -- reg in the assignment. src must be an allocatable reg,
413 -- otherwise it wouldn't be in r_dying.
414 _virt -> case lookupUFM assig src of
415 Nothing -> panic "raInsn"
417 setAssigR (addToUFM (delFromUFM assig src) dst loc)
419 -- we have elimianted this instruction
421 freeregs <- getFreeRegsR
423 pprTrace "raInsn" (text "ELIMINATED: " <> docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ text (show freeregs) $$ ppr assig) $ do
425 return (new_instrs, [])
427 other -> genRaInsn block_live new_instrs instr
428 (uniqSetToList $ liveDieRead live)
429 (uniqSetToList $ liveDieWrite live)
432 raInsn block_live new_instrs li
433 = pprPanic "raInsn" (text "no match for:" <> ppr li)
436 genRaInsn block_live new_instrs instr r_dying w_dying =
437 case regUsage instr of { RU read written ->
438 case partition isRealReg written of { (real_written1,virt_written) ->
441 real_written = [ r | RealReg r <- real_written1 ]
443 -- we don't need to do anything with real registers that are
444 -- only read by this instr. (the list is typically ~2 elements,
445 -- so using nub isn't a problem).
446 virt_read = nub (filter isVirtualReg read)
449 -- (a) save any temporaries which will be clobbered by this instruction
450 clobber_saves <- saveClobberedTemps real_written r_dying
453 freeregs <- getFreeRegsR
455 pprTrace "raInsn" (docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ ppr virt_read <+> ppr virt_written $$ text (show freeregs) $$ ppr assig) $ do
458 -- (b), (c) allocate real regs for all regs read by this instruction.
459 (r_spills, r_allocd) <-
460 allocateRegsAndSpill True{-reading-} virt_read [] [] virt_read
462 -- (d) Update block map for new destinations
463 -- NB. do this before removing dead regs from the assignment, because
464 -- these dead regs might in fact be live in the jump targets (they're
465 -- only dead in the code that follows in the current basic block).
466 (fixup_blocks, adjusted_instr)
467 <- joinToTargets block_live [] instr (jumpDests instr [])
469 -- (e) Delete all register assignments for temps which are read
470 -- (only) and die here. Update the free register list.
473 -- (f) Mark regs which are clobbered as unallocatable
474 clobberRegs real_written
476 -- (g) Allocate registers for temporaries *written* (only)
477 (w_spills, w_allocd) <-
478 allocateRegsAndSpill False{-writing-} virt_written [] [] virt_written
480 -- (h) Release registers for temps which are written here and not
485 -- (i) Patch the instruction
486 patch_map = listToUFM [ (t,RealReg r) |
487 (t,r) <- zip virt_read r_allocd
488 ++ zip virt_written w_allocd ]
490 patched_instr = patchRegs adjusted_instr patchLookup
491 patchLookup x = case lookupUFM patch_map x of
496 -- pprTrace "patched" (docToSDoc (pprInstr patched_instr)) $ do
498 -- (j) free up stack slots for dead spilled regs
499 -- TODO (can't be bothered right now)
501 -- erase reg->reg moves where the source and destination are the same.
502 -- If the src temp didn't die in this instr but happened to be allocated
503 -- to the same real reg as the destination, then we can erase the move anyway.
504 squashed_instr = case isRegRegMove patched_instr of
509 return (squashed_instr ++ w_spills ++ reverse r_spills
510 ++ clobber_saves ++ new_instrs,
514 -- -----------------------------------------------------------------------------
517 releaseRegs regs = do
522 loop assig free _ | free `seq` False = undefined
523 loop assig free [] = do setAssigR assig; setFreeRegsR free; return ()
524 loop assig free (RealReg r : rs) = loop assig (releaseReg r free) rs
525 loop assig free (r:rs) =
526 case lookupUFM assig r of
527 Just (InBoth real _) -> loop (delFromUFM assig r) (releaseReg real free) rs
528 Just (InReg real) -> loop (delFromUFM assig r) (releaseReg real free) rs
529 _other -> loop (delFromUFM assig r) free rs
531 -- -----------------------------------------------------------------------------
532 -- Clobber real registers
535 For each temp in a register that is going to be clobbered:
536 - if the temp dies after this instruction, do nothing
537 - otherwise, put it somewhere safe (another reg if possible,
538 otherwise spill and record InBoth in the assignment).
540 for allocateRegs on the temps *read*,
541 - clobbered regs are allocatable.
543 for allocateRegs on the temps *written*,
544 - clobbered regs are not allocatable.
548 :: [RegNo] -- real registers clobbered by this instruction
549 -> [Reg] -- registers which are no longer live after this insn
550 -> RegM [Instr] -- return: instructions to spill any temps that will
553 saveClobberedTemps [] _ = return [] -- common case
554 saveClobberedTemps clobbered dying = do
557 to_spill = [ (temp,reg) | (temp, InReg reg) <- ufmToList assig,
558 reg `elem` clobbered,
559 temp `notElem` map getUnique dying ]
561 (instrs,assig') <- clobber assig [] to_spill
565 clobber assig instrs [] = return (instrs,assig)
566 clobber assig instrs ((temp,reg):rest)
568 --ToDo: copy it to another register if possible
569 (spill,slot) <- spillR (RealReg reg) temp
570 recordSpill (SpillClobber temp)
572 let new_assign = addToUFM assig temp (InBoth reg slot)
573 clobber new_assign (spill : COMMENT FSLIT("spill clobber") : instrs) rest
575 clobberRegs :: [RegNo] -> RegM ()
576 clobberRegs [] = return () -- common case
577 clobberRegs clobbered = do
578 freeregs <- getFreeRegsR
579 setFreeRegsR $! foldr allocateReg freeregs clobbered
581 setAssigR $! clobber assig (ufmToList assig)
583 -- if the temp was InReg and clobbered, then we will have
584 -- saved it in saveClobberedTemps above. So the only case
585 -- we have to worry about here is InBoth. Note that this
586 -- also catches temps which were loaded up during allocation
587 -- of read registers, not just those saved in saveClobberedTemps.
588 clobber assig [] = assig
589 clobber assig ((temp, InBoth reg slot) : rest)
590 | reg `elem` clobbered
591 = clobber (addToUFM assig temp (InMem slot)) rest
592 clobber assig (entry:rest)
595 -- -----------------------------------------------------------------------------
596 -- allocateRegsAndSpill
598 -- This function does several things:
599 -- For each temporary referred to by this instruction,
600 -- we allocate a real register (spilling another temporary if necessary).
601 -- We load the temporary up from memory if necessary.
602 -- We also update the register assignment in the process, and
603 -- the list of free registers and free stack slots.
606 :: Bool -- True <=> reading (load up spilled regs)
607 -> [Reg] -- don't push these out
608 -> [Instr] -- spill insns
609 -> [RegNo] -- real registers allocated (accum.)
610 -> [Reg] -- temps to allocate
611 -> RegM ([Instr], [RegNo])
613 allocateRegsAndSpill reading keep spills alloc []
614 = return (spills,reverse alloc)
616 allocateRegsAndSpill reading keep spills alloc (r:rs) = do
618 case lookupUFM assig r of
619 -- case (1a): already in a register
620 Just (InReg my_reg) ->
621 allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
623 -- case (1b): already in a register (and memory)
624 -- NB1. if we're writing this register, update its assignemnt to be
625 -- InReg, because the memory value is no longer valid.
626 -- NB2. This is why we must process written registers here, even if they
627 -- are also read by the same instruction.
628 Just (InBoth my_reg mem) -> do
629 when (not reading) (setAssigR (addToUFM assig r (InReg my_reg)))
630 allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
632 -- Not already in a register, so we need to find a free one...
634 freeregs <- getFreeRegsR
636 case getFreeRegs (regClass r) freeregs of
638 -- case (2): we have a free register
640 spills' <- loadTemp reading r loc my_reg spills
642 | Just (InMem slot) <- loc, reading = InBoth my_reg slot
643 | otherwise = InReg my_reg
644 setAssigR (addToUFM assig r $! new_loc)
645 setFreeRegsR (allocateReg my_reg freeregs)
646 allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
648 -- case (3): we need to push something out to free up a register
651 keep' = map getUnique keep
652 candidates1 = [ (temp,reg,mem)
653 | (temp, InBoth reg mem) <- ufmToList assig,
654 temp `notElem` keep', regClass (RealReg reg) == regClass r ]
655 candidates2 = [ (temp,reg)
656 | (temp, InReg reg) <- ufmToList assig,
657 temp `notElem` keep', regClass (RealReg reg) == regClass r ]
659 ASSERT2(not (null candidates1 && null candidates2),
660 text (show freeregs) <+> ppr r <+> ppr assig) do
664 -- we have a temporary that is in both register and mem,
665 -- just free up its register for use.
667 (temp,my_reg,slot):_ -> do
668 spills' <- loadTemp reading r loc my_reg spills
670 assig1 = addToUFM assig temp (InMem slot)
671 assig2 = addToUFM assig1 r (InReg my_reg)
674 allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
676 -- otherwise, we need to spill a temporary that currently
677 -- resides in a register.
682 -- TODO: plenty of room for optimisation in choosing which temp
683 -- to spill. We just pick the first one that isn't used in
684 -- the current instruction for now.
686 let (temp_to_push_out, my_reg) = myHead "regalloc" candidates2
688 (spill_insn, slot) <- spillR (RealReg my_reg) temp_to_push_out
689 let spill_store = (if reading then id else reverse)
690 [ COMMENT FSLIT("spill alloc")
693 -- record that this temp was spilled
694 recordSpill (SpillAlloc temp_to_push_out)
696 -- update the register assignment
697 let assig1 = addToUFM assig temp_to_push_out (InMem slot)
698 let assig2 = addToUFM assig1 r (InReg my_reg)
701 -- if need be, load up a spilled temp into the reg we've just freed up.
702 spills' <- loadTemp reading r loc my_reg spills
704 allocateRegsAndSpill reading keep
705 (spill_store ++ spills')
709 -- | Load up a spilled temporary if we need to.
712 -> Reg -- the temp being loaded
713 -> Maybe Loc -- the current location of this temp
714 -> RegNo -- the hreg to load the temp into
718 loadTemp True vreg (Just (InMem slot)) hreg spills
720 insn <- loadR (RealReg hreg) slot
721 recordSpill (SpillLoad $ getUnique vreg)
722 return $ COMMENT FSLIT("spill load") : insn : spills
724 loadTemp _ _ _ _ spills =
728 myHead s [] = panic s
731 -- -----------------------------------------------------------------------------
732 -- Joining a jump instruction to its targets
734 -- The first time we encounter a jump to a particular basic block, we
735 -- record the assignment of temporaries. The next time we encounter a
736 -- jump to the same block, we compare our current assignment to the
737 -- stored one. They might be different if spilling has occrred in one
738 -- branch; so some fixup code will be required to match up the
746 -> RegM ([NatBasicBlock], Instr)
748 joinToTargets block_live new_blocks instr []
749 = return (new_blocks, instr)
751 joinToTargets block_live new_blocks instr (dest:dests) = do
752 block_assig <- getBlockAssigR
755 -- adjust the assignment to remove any registers which are not
756 -- live on entry to the destination block.
757 adjusted_assig = filterUFM_Directly still_live assig
759 live_set = lookItUp "joinToTargets" block_live dest
760 still_live uniq _ = uniq `elemUniqSet_Directly` live_set
762 -- and free up those registers which are now free.
764 [ r | (reg, loc) <- ufmToList assig,
765 not (elemUniqSet_Directly reg live_set),
768 regsOfLoc (InReg r) = [r]
769 regsOfLoc (InBoth r _) = [r]
770 regsOfLoc (InMem _) = []
772 case lookupUFM block_assig dest of
773 -- Nothing <=> this is the first time we jumped to this
776 freeregs <- getFreeRegsR
777 let freeregs' = foldr releaseReg freeregs to_free
778 setBlockAssigR (addToUFM block_assig dest
779 (freeregs',adjusted_assig))
780 joinToTargets block_live new_blocks instr dests
782 Just (freeregs,dest_assig)
784 -- the assignments match
785 | ufmToList dest_assig == ufmToList adjusted_assig
786 -> joinToTargets block_live new_blocks instr dests
793 let graph = makeRegMovementGraph adjusted_assig dest_assig
794 let sccs = stronglyConnCompR graph
795 fixUpInstrs <- mapM (handleComponent delta instr) sccs
797 block_id <- getUniqueR
798 let block = BasicBlock (BlockId block_id) $
799 concat fixUpInstrs ++ mkBranchInstr dest
801 let instr' = patchJump instr dest (BlockId block_id)
803 joinToTargets block_live (block : new_blocks) instr' dests
806 -- | Construct a graph of register/spill movements.
808 -- We cut some corners by
809 -- a) not handling cyclic components
810 -- b) not handling memory-to-memory moves.
812 -- Cyclic components seem to occur only very rarely,
813 -- and we don't need memory-to-memory moves because we
814 -- make sure that every temporary always gets its own
817 makeRegMovementGraph :: RegMap Loc -> RegMap Loc -> [(Unique, Loc, [Loc])]
818 makeRegMovementGraph adjusted_assig dest_assig
821 = expandNode vreg src
822 $ lookupWithDefaultUFM_Directly
824 (panic "RegisterAlloc.joinToTargets")
827 in [ node | (vreg, src) <- ufmToList adjusted_assig
828 , node <- mkNodes src vreg ]
830 -- The InBoth handling is a little tricky here. If
831 -- the destination is InBoth, then we must ensure that
832 -- the value ends up in both locations. An InBoth
833 -- destination must conflict with an InReg or InMem
834 -- source, so we expand an InBoth destination as
835 -- necessary. An InBoth source is slightly different:
836 -- we only care about the register that the source value
837 -- is in, so that we can move it to the destinations.
839 expandNode vreg loc@(InReg src) (InBoth dst mem)
840 | src == dst = [(vreg, loc, [InMem mem])]
841 | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
843 expandNode vreg loc@(InMem src) (InBoth dst mem)
844 | src == mem = [(vreg, loc, [InReg dst])]
845 | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
847 expandNode vreg loc@(InBoth _ src) (InMem dst)
848 | src == dst = [] -- guaranteed to be true
850 expandNode vreg loc@(InBoth src _) (InReg dst)
853 expandNode vreg loc@(InBoth src _) dst
854 = expandNode vreg (InReg src) dst
856 expandNode vreg src dst
858 | otherwise = [(vreg, src, [dst])]
861 -- | Make a move instruction between these two locations so we
862 -- can join together allocations for different basic blocks.
864 makeMove :: Int -> Unique -> Loc -> Loc -> RegM Instr
865 makeMove delta vreg (InReg src) (InReg dst)
866 = do recordSpill (SpillJoinRR vreg)
867 return $ mkRegRegMoveInstr (RealReg src) (RealReg dst)
869 makeMove delta vreg (InMem src) (InReg dst)
870 = do recordSpill (SpillJoinRM vreg)
871 return $ mkLoadInstr (RealReg dst) delta src
873 makeMove delta vreg (InReg src) (InMem dst)
874 = do recordSpill (SpillJoinRM vreg)
875 return $ mkSpillInstr (RealReg src) delta dst
877 makeMove delta vreg src dst
878 = panic $ "makeMove " ++ show vreg ++ " (" ++ show src ++ ") ("
880 ++ " (workaround: use -fviaC)"
883 -- we have eliminated any possibility of single-node cylces
884 -- in expandNode above.
885 handleComponent :: Int -> Instr -> SCC (Unique, Loc, [Loc]) -> RegM [Instr]
886 handleComponent delta instr (AcyclicSCC (vreg,src,dsts))
887 = mapM (makeMove delta vreg src) dsts
889 -- we can not have cycles that involve memory
890 -- locations as source nor as single destination
891 -- because memory locations (stack slots) are
892 -- allocated exclusively for a virtual register and
893 -- therefore can not require a fixup
894 handleComponent delta instr (CyclicSCC ((vreg,src@(InReg sreg),dsts):rest))
896 spill_id <- getUniqueR
897 (saveInstr,slot) <- spillR (RealReg sreg) spill_id
898 remainingFixUps <- mapM (handleComponent delta instr) (stronglyConnCompR rest)
899 restoreAndFixInstr <- getRestoreMoves dsts slot
900 return ([instr] ++ concat remainingFixUps ++ restoreAndFixInstr)
903 getRestoreMoves [r@(InReg reg), mem@(InMem _)] slot
905 restoreToReg <- loadR (RealReg reg) slot
906 moveInstr <- makeMove delta vreg r mem
907 return $ [COMMENT FSLIT("spill join move"), restoreToReg, moveInstr]
909 getRestoreMoves [InReg reg] slot
910 = loadR (RealReg reg) slot >>= return . (:[])
912 getRestoreMoves [InMem _] _ = panic "getRestoreMoves can not handle memory only restores"
913 getRestoreMoves _ _ = panic "getRestoreMoves unknown case"
916 handleComponent delta instr (CyclicSCC _)
917 = panic "Register Allocator: handleComponent cyclic"
921 -- -----------------------------------------------------------------------------
922 -- The register allocator's monad.
924 -- Here we keep all the state that the register allocator keeps track
925 -- of as it walks the instructions in a basic block.
929 ra_blockassig :: BlockAssignment,
930 -- The current mapping from basic blocks to
931 -- the register assignments at the beginning of that block.
932 ra_freeregs :: {-#UNPACK#-}!FreeRegs, -- free machine registers
933 ra_assig :: RegMap Loc, -- assignment of temps to locations
934 ra_delta :: Int, -- current stack delta
935 ra_stack :: StackMap, -- free stack slots for spilling
936 ra_us :: UniqSupply, -- unique supply for generating names
939 -- Record why things were spilled, for -ddrop-asm-stats.
940 -- Just keep a list here instead of a map of regs -> reasons.
941 -- We don't want to slow down the allocator if we're not going to emit the stats.
942 ra_spills :: [SpillReason]
945 newtype RegM a = RegM { unReg :: RA_State -> (# RA_State, a #) }
948 instance Monad RegM where
949 m >>= k = RegM $ \s -> case unReg m s of { (# s, a #) -> unReg (k a) s }
950 return a = RegM $ \s -> (# s, a #)
952 runR :: BlockAssignment -> FreeRegs -> RegMap Loc -> StackMap -> UniqSupply
953 -> RegM a -> (BlockAssignment, StackMap, RegAllocStats, a)
954 runR block_assig freeregs assig stack us thing =
955 case unReg thing (RA_State{ ra_blockassig=block_assig, ra_freeregs=freeregs,
956 ra_assig=assig, ra_delta=0{-???-}, ra_stack=stack,
957 ra_us = us, ra_spills = [] }) of
958 (# state'@RA_State{ ra_blockassig=block_assig, ra_stack=stack', ra_spills=spills' }, returned_thing #)
959 -> (block_assig, stack', makeRAStats state', returned_thing)
961 spillR :: Reg -> Unique -> RegM (Instr, Int)
962 spillR reg temp = RegM $ \ s@RA_State{ra_delta=delta, ra_stack=stack} ->
963 let (stack',slot) = getStackSlotFor stack temp
964 instr = mkSpillInstr reg delta slot
966 (# s{ra_stack=stack'}, (instr,slot) #)
968 loadR :: Reg -> Int -> RegM Instr
969 loadR reg slot = RegM $ \ s@RA_State{ra_delta=delta} ->
970 (# s, mkLoadInstr reg delta slot #)
972 getFreeRegsR :: RegM FreeRegs
973 getFreeRegsR = RegM $ \ s@RA_State{ra_freeregs = freeregs} ->
976 setFreeRegsR :: FreeRegs -> RegM ()
977 setFreeRegsR regs = RegM $ \ s ->
978 (# s{ra_freeregs = regs}, () #)
980 getAssigR :: RegM (RegMap Loc)
981 getAssigR = RegM $ \ s@RA_State{ra_assig = assig} ->
984 setAssigR :: RegMap Loc -> RegM ()
985 setAssigR assig = RegM $ \ s ->
986 (# s{ra_assig=assig}, () #)
988 getBlockAssigR :: RegM BlockAssignment
989 getBlockAssigR = RegM $ \ s@RA_State{ra_blockassig = assig} ->
992 setBlockAssigR :: BlockAssignment -> RegM ()
993 setBlockAssigR assig = RegM $ \ s ->
994 (# s{ra_blockassig = assig}, () #)
996 setDeltaR :: Int -> RegM ()
997 setDeltaR n = RegM $ \ s ->
998 (# s{ra_delta = n}, () #)
1000 getDeltaR :: RegM Int
1001 getDeltaR = RegM $ \s -> (# s, ra_delta s #)
1003 getUniqueR :: RegM Unique
1004 getUniqueR = RegM $ \s ->
1005 case splitUniqSupply (ra_us s) of
1006 (us1, us2) -> (# s{ra_us = us2}, uniqFromSupply us1 #)
1008 -- | Record that a spill instruction was inserted, for profiling.
1009 recordSpill :: SpillReason -> RegM ()
1011 = RegM $ \s -> (# s { ra_spills = spill : ra_spills s}, () #)
1013 -- -----------------------------------------------------------------------------
1015 -- | Reasons why instructions might be inserted by the spiller.
1016 -- Used when generating stats for -ddrop-asm-stats.
1019 = SpillAlloc !Unique -- ^ vreg was spilled to a slot so we could use its
1020 -- current hreg for another vreg
1021 | SpillClobber !Unique -- ^ vreg was moved because its hreg was clobbered
1022 | SpillLoad !Unique -- ^ vreg was loaded from a spill slot
1024 | SpillJoinRR !Unique -- ^ reg-reg move inserted during join to targets
1025 | SpillJoinRM !Unique -- ^ reg-mem move inserted during join to targets
1028 -- | Used to carry interesting stats out of the register allocator.
1031 { ra_spillInstrs :: UniqFM [Int] }
1034 -- | Make register allocator stats from its final state.
1035 makeRAStats :: RA_State -> RegAllocStats
1038 { ra_spillInstrs = binSpillReasons (ra_spills state) }
1041 -- | Build a map of how many times each reg was alloced, clobbered, loaded etc.
1043 :: [SpillReason] -> UniqFM [Int]
1045 binSpillReasons reasons
1049 (map (\reason -> case reason of
1050 SpillAlloc r -> (r, [1, 0, 0, 0, 0])
1051 SpillClobber r -> (r, [0, 1, 0, 0, 0])
1052 SpillLoad r -> (r, [0, 0, 1, 0, 0])
1053 SpillJoinRR r -> (r, [0, 0, 0, 1, 0])
1054 SpillJoinRM r -> (r, [0, 0, 0, 0, 1])) reasons)
1057 -- | Pretty print some RegAllocStats
1058 pprStats :: [RegAllocStats] -> SDoc
1060 = let spills = foldl' (plusUFM_C (zipWith (+)))
1062 $ map ra_spillInstrs statss
1064 spillTotals = foldl' (zipWith (+))
1068 pprSpill (reg, spills)
1069 = parens $ (hcat $ punctuate (text ", ") (doubleQuotes (ppr reg) : map ppr spills))
1071 in ( text "-- spills-added-total"
1072 $$ text "-- (allocs, clobbers, loads, joinRR, joinRM)"
1073 $$ (parens $ (hcat $ punctuate (text ", ") (map ppr spillTotals)))
1075 $$ text "-- spills-added"
1076 $$ text "-- (reg_name, allocs, clobbers, loads, joinRR, joinRM)"
1077 $$ (vcat $ map pprSpill
1082 -- -----------------------------------------------------------------------------
1086 my_fromJust s p Nothing = pprPanic ("fromJust: " ++ s) p
1087 my_fromJust s p (Just x) = x
1089 my_fromJust _ _ = fromJust
1092 lookItUp :: Uniquable b => String -> UniqFM a -> b -> a
1093 lookItUp str fm x = my_fromJust str (ppr (getUnique x)) (lookupUFM fm x)