2 -- The above warning supression flag is a temporary kludge.
3 -- While working on this module you are encouraged to remove it and fix
4 -- any warnings in the module. See
5 -- http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions#Warnings
8 -----------------------------------------------------------------------------
10 -- The register allocator
12 -- (c) The University of Glasgow 2004
14 -----------------------------------------------------------------------------
17 The algorithm is roughly:
19 1) Compute strongly connected components of the basic block list.
21 2) Compute liveness (mapping from pseudo register to
24 3) Walk instructions in each basic block. We keep track of
25 (a) Free real registers (a bitmap?)
26 (b) Current assignment of temporaries to machine registers and/or
27 spill slots (call this the "assignment").
28 (c) Partial mapping from basic block ids to a virt-to-loc mapping.
29 When we first encounter a branch to a basic block,
30 we fill in its entry in this table with the current mapping.
33 (a) For each real register clobbered by this instruction:
34 If a temporary resides in it,
35 If the temporary is live after this instruction,
36 Move the temporary to another (non-clobbered & free) reg,
37 or spill it to memory. Mark the temporary as residing
38 in both memory and a register if it was spilled (it might
39 need to be read by this instruction).
40 (ToDo: this is wrong for jump instructions?)
42 (b) For each temporary *read* by the instruction:
43 If the temporary does not have a real register allocation:
44 - Allocate a real register from the free list. If
46 - Find a temporary to spill. Pick one that is
47 not used in this instruction (ToDo: not
49 - generate a spill instruction
50 - If the temporary was previously spilled,
51 generate an instruction to read the temp from its spill loc.
52 (optimisation: if we can see that a real register is going to
53 be used soon, then don't use it for allocation).
55 (c) Update the current assignment
57 (d) If the intstruction is a branch:
58 if the destination block already has a register assignment,
59 Generate a new block with fixup code and redirect the
60 jump to the new block.
62 Update the block id->assignment mapping with the current
65 (e) Delete all register assignments for temps which are read
66 (only) and die here. Update the free register list.
68 (f) Mark all registers clobbered by this instruction as not free,
69 and mark temporaries which have been spilled due to clobbering
70 as in memory (step (a) marks then as in both mem & reg).
72 (g) For each temporary *written* by this instruction:
73 Allocate a real register as for (b), spilling something
75 - except when updating the assignment, drop any memory
76 locations that the temporary was previously in, since
77 they will be no longer valid after this instruction.
79 (h) Delete all register assignments for temps which are
80 written and die here (there should rarely be any). Update
81 the free register list.
83 (i) Rewrite the instruction with the new mapping.
85 (j) For each spilled reg known to be now dead, re-add its stack slot
90 module RegAllocLinear (
92 RegAllocStats, pprStats
95 #include "HsVersions.h"
104 import Unique ( Uniquable(getUnique), Unique )
112 import Data.Maybe ( fromJust )
114 import Data.List ( nub, partition, mapAccumL, foldl')
115 import Control.Monad ( when )
120 -- -----------------------------------------------------------------------------
121 -- The free register set
123 -- This needs to be *efficient*
125 {- Here's an inefficient 'executable specification' of the FreeRegs data type:
126 type FreeRegs = [RegNo]
129 releaseReg n f = if n `elem` f then f else (n : f)
130 initFreeRegs = allocatableRegs
131 getFreeRegs cls f = filter ( (==cls) . regClass . RealReg ) f
132 allocateReg f r = filter (/= r) f
135 #if defined(powerpc_TARGET_ARCH)
137 -- The PowerPC has 32 integer and 32 floating point registers.
138 -- This is 32bit PowerPC, so Word64 is inefficient - two Word32s are much
140 -- Note that when getFreeRegs scans for free registers, it starts at register
141 -- 31 and counts down. This is a hack for the PowerPC - the higher-numbered
142 -- registers are callee-saves, while the lower regs are caller-saves, so it
143 -- makes sense to start at the high end.
144 -- Apart from that, the code does nothing PowerPC-specific, so feel free to
145 -- add your favourite platform to the #if (if you have 64 registers but only
148 data FreeRegs = FreeRegs !Word32 !Word32
149 deriving( Show ) -- The Show is used in an ASSERT
151 noFreeRegs :: FreeRegs
152 noFreeRegs = FreeRegs 0 0
154 releaseReg :: RegNo -> FreeRegs -> FreeRegs
155 releaseReg r (FreeRegs g f)
156 | r > 31 = FreeRegs g (f .|. (1 `shiftL` (fromIntegral r - 32)))
157 | otherwise = FreeRegs (g .|. (1 `shiftL` fromIntegral r)) f
159 initFreeRegs :: FreeRegs
160 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
162 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
163 getFreeRegs cls (FreeRegs g f)
164 | RcDouble <- cls = go f (0x80000000) 63
165 | RcInteger <- cls = go g (0x80000000) 31
168 go x m i | x .&. m /= 0 = i : (go x (m `shiftR` 1) $! i-1)
169 | otherwise = go x (m `shiftR` 1) $! i-1
171 allocateReg :: RegNo -> FreeRegs -> FreeRegs
172 allocateReg r (FreeRegs g f)
173 | r > 31 = FreeRegs g (f .&. complement (1 `shiftL` (fromIntegral r - 32)))
174 | otherwise = FreeRegs (g .&. complement (1 `shiftL` fromIntegral r)) f
178 -- If we have less than 32 registers, or if we have efficient 64-bit words,
179 -- we will just use a single bitfield.
181 #if defined(alpha_TARGET_ARCH)
182 type FreeRegs = Word64
184 type FreeRegs = Word32
187 noFreeRegs :: FreeRegs
190 releaseReg :: RegNo -> FreeRegs -> FreeRegs
191 releaseReg n f = f .|. (1 `shiftL` n)
193 initFreeRegs :: FreeRegs
194 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
196 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
197 getFreeRegs cls f = go f 0
200 | n .&. 1 /= 0 && regClass (RealReg m) == cls
201 = m : (go (n `shiftR` 1) $! (m+1))
203 = go (n `shiftR` 1) $! (m+1)
204 -- ToDo: there's no point looking through all the integer registers
205 -- in order to find a floating-point one.
207 allocateReg :: RegNo -> FreeRegs -> FreeRegs
208 allocateReg r f = f .&. complement (1 `shiftL` fromIntegral r)
212 -- -----------------------------------------------------------------------------
213 -- The assignment of virtual registers to stack slots
215 -- We have lots of stack slots. Memory-to-memory moves are a pain on most
216 -- architectures. Therefore, we avoid having to generate memory-to-memory moves
217 -- by simply giving every virtual register its own stack slot.
219 -- The StackMap stack map keeps track of virtual register - stack slot
220 -- associations and of which stack slots are still free. Once it has been
221 -- associated, a stack slot is never "freed" or removed from the StackMap again,
222 -- it remains associated until we are done with the current CmmProc.
225 data StackMap = StackMap [StackSlot] (UniqFM StackSlot)
227 emptyStackMap :: StackMap
228 emptyStackMap = StackMap [0..maxSpillSlots] emptyUFM
230 getStackSlotFor :: StackMap -> Unique -> (StackMap,Int)
231 getStackSlotFor fs@(StackMap [] reserved) reg
232 = panic "RegAllocLinear.getStackSlotFor: out of stack slots"
233 getStackSlotFor fs@(StackMap (freeSlot:stack') reserved) reg =
234 case lookupUFM reserved reg of
235 Just slot -> (fs,slot)
236 Nothing -> (StackMap stack' (addToUFM reserved reg freeSlot), freeSlot)
238 -- -----------------------------------------------------------------------------
239 -- Top level of the register allocator
241 -- Allocate registers
244 -> UniqSM (NatCmmTop, Maybe RegAllocStats)
246 regAlloc cmm@(CmmData sec d)
251 regAlloc cmm@(CmmProc (LiveInfo info _ _) lbl params [])
253 ( CmmProc info lbl params []
256 regAlloc cmm@(CmmProc static lbl params comps)
257 | LiveInfo info (Just first_id) block_live <- static
259 -- do register allocation on each component.
260 (final_blocks, stats)
261 <- linearRegAlloc block_live
262 $ map (\b -> case b of
263 BasicBlock i [b] -> AcyclicSCC b
264 BasicBlock i bs -> CyclicSCC bs)
267 -- make sure the block that was first in the input list
268 -- stays at the front of the output
269 let ((first':_), rest')
270 = partition ((== first_id) . blockId) final_blocks
272 return ( CmmProc info lbl params (first' : rest')
277 -- -----------------------------------------------------------------------------
278 -- Linear sweep to allocate registers
280 data Loc = InReg {-# UNPACK #-} !RegNo
281 | InMem {-# UNPACK #-} !Int -- stack slot
282 | InBoth {-# UNPACK #-} !RegNo
283 {-# UNPACK #-} !Int -- stack slot
284 deriving (Eq, Show, Ord)
287 A temporary can be marked as living in both a register and memory
288 (InBoth), for example if it was recently loaded from a spill location.
289 This makes it cheap to spill (no save instruction required), but we
290 have to be careful to turn this into InReg if the value in the
293 This is also useful when a temporary is about to be clobbered. We
294 save it in a spill location, but mark it as InBoth because the current
295 instruction might still want to read it.
299 instance Outputable Loc where
300 ppr l = text (show l)
304 -- | Do register allocation on some basic blocks.
307 :: BlockMap RegSet -- ^ live regs on entry to each basic block
308 -> [SCC LiveBasicBlock] -- ^ instructions annotated with "deaths"
309 -> UniqSM ([NatBasicBlock], RegAllocStats)
311 linearRegAlloc block_live sccs
313 let (block_assig', stackMap', stats, blocks) =
314 runR emptyBlockMap initFreeRegs emptyRegMap emptyStackMap us
315 $ linearRA_SCCs block_live [] sccs
317 return (blocks, stats)
319 linearRA_SCCs block_live blocksAcc []
320 = return $ reverse blocksAcc
322 linearRA_SCCs block_live blocksAcc (AcyclicSCC block : sccs)
323 = do blocks' <- processBlock block_live block
324 linearRA_SCCs block_live
325 ((reverse blocks') ++ blocksAcc)
328 linearRA_SCCs block_live blocksAcc (CyclicSCC blocks : sccs)
329 = do blockss' <- mapM (processBlock block_live) blocks
330 linearRA_SCCs block_live
331 (reverse (concat blockss') ++ blocksAcc)
335 -- | Do register allocation on this basic block
338 :: BlockMap RegSet -- ^ live regs on entry to each basic block
339 -> LiveBasicBlock -- ^ block to do register allocation on
340 -> RegM [NatBasicBlock] -- ^ block with registers allocated
342 processBlock block_live (BasicBlock id instrs)
345 <- linearRA block_live [] [] instrs
347 return $ BasicBlock id instrs' : fixups
350 -- | Load the freeregs and current reg assignment into the RegM state
351 -- for the basic block with this BlockId.
352 initBlock :: BlockId -> RegM ()
354 = do block_assig <- getBlockAssigR
355 case lookupUFM block_assig id of
356 -- no prior info about this block: assume everything is
357 -- free and the assignment is empty.
359 -> do setFreeRegsR initFreeRegs
360 setAssigR emptyRegMap
362 -- load info about register assignments leading into this block.
363 Just (freeregs, assig)
364 -> do setFreeRegsR freeregs
370 -> [Instr] -> [NatBasicBlock] -> [LiveInstr]
371 -> RegM ([Instr], [NatBasicBlock])
373 linearRA block_live instr_acc fixups []
374 = return (reverse instr_acc, fixups)
376 linearRA block_live instr_acc fixups (instr:instrs)
377 = do (instr_acc', new_fixups) <- raInsn block_live instr_acc instr
378 linearRA block_live instr_acc' (new_fixups++fixups) instrs
380 -- -----------------------------------------------------------------------------
381 -- Register allocation for a single instruction
383 type BlockAssignment = BlockMap (FreeRegs, RegMap Loc)
385 raInsn :: BlockMap RegSet -- Live temporaries at each basic block
386 -> [Instr] -- new instructions (accum.)
387 -> LiveInstr -- the instruction (with "deaths")
389 [Instr], -- new instructions
390 [NatBasicBlock] -- extra fixup blocks
393 raInsn block_live new_instrs (Instr instr@(COMMENT _) Nothing)
394 = return (new_instrs, [])
396 raInsn block_live new_instrs (Instr instr@(DELTA n) Nothing)
399 return (new_instrs, [])
401 raInsn block_live new_instrs (Instr instr (Just live))
405 -- If we have a reg->reg move between virtual registers, where the
406 -- src register is not live after this instruction, and the dst
407 -- register does not already have an assignment,
408 -- and the source register is assigned to a register, not to a spill slot,
409 -- then we can eliminate the instruction.
410 -- (we can't eliminitate it if the source register is on the stack, because
411 -- we do not want to use one spill slot for different virtual registers)
412 case isRegRegMove instr of
413 Just (src,dst) | src `elementOfUniqSet` (liveDieRead live),
415 not (dst `elemUFM` assig),
416 Just (InReg _) <- (lookupUFM assig src) -> do
418 RealReg i -> setAssigR (addToUFM assig dst (InReg i))
419 -- if src is a fixed reg, then we just map dest to this
420 -- reg in the assignment. src must be an allocatable reg,
421 -- otherwise it wouldn't be in r_dying.
422 _virt -> case lookupUFM assig src of
423 Nothing -> panic "raInsn"
425 setAssigR (addToUFM (delFromUFM assig src) dst loc)
427 -- we have elimianted this instruction
429 freeregs <- getFreeRegsR
431 pprTrace "raInsn" (text "ELIMINATED: " <> docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ text (show freeregs) $$ ppr assig) $ do
433 return (new_instrs, [])
435 other -> genRaInsn block_live new_instrs instr
436 (uniqSetToList $ liveDieRead live)
437 (uniqSetToList $ liveDieWrite live)
440 raInsn block_live new_instrs li
441 = pprPanic "raInsn" (text "no match for:" <> ppr li)
444 genRaInsn block_live new_instrs instr r_dying w_dying =
445 case regUsage instr of { RU read written ->
446 case partition isRealReg written of { (real_written1,virt_written) ->
449 real_written = [ r | RealReg r <- real_written1 ]
451 -- we don't need to do anything with real registers that are
452 -- only read by this instr. (the list is typically ~2 elements,
453 -- so using nub isn't a problem).
454 virt_read = nub (filter isVirtualReg read)
457 -- (a) save any temporaries which will be clobbered by this instruction
458 clobber_saves <- saveClobberedTemps real_written r_dying
461 freeregs <- getFreeRegsR
463 pprTrace "raInsn" (docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ ppr virt_read <+> ppr virt_written $$ text (show freeregs) $$ ppr assig) $ do
466 -- (b), (c) allocate real regs for all regs read by this instruction.
467 (r_spills, r_allocd) <-
468 allocateRegsAndSpill True{-reading-} virt_read [] [] virt_read
470 -- (d) Update block map for new destinations
471 -- NB. do this before removing dead regs from the assignment, because
472 -- these dead regs might in fact be live in the jump targets (they're
473 -- only dead in the code that follows in the current basic block).
474 (fixup_blocks, adjusted_instr)
475 <- joinToTargets block_live [] instr (jumpDests instr [])
477 -- (e) Delete all register assignments for temps which are read
478 -- (only) and die here. Update the free register list.
481 -- (f) Mark regs which are clobbered as unallocatable
482 clobberRegs real_written
484 -- (g) Allocate registers for temporaries *written* (only)
485 (w_spills, w_allocd) <-
486 allocateRegsAndSpill False{-writing-} virt_written [] [] virt_written
488 -- (h) Release registers for temps which are written here and not
493 -- (i) Patch the instruction
494 patch_map = listToUFM [ (t,RealReg r) |
495 (t,r) <- zip virt_read r_allocd
496 ++ zip virt_written w_allocd ]
498 patched_instr = patchRegs adjusted_instr patchLookup
499 patchLookup x = case lookupUFM patch_map x of
504 -- pprTrace "patched" (docToSDoc (pprInstr patched_instr)) $ do
506 -- (j) free up stack slots for dead spilled regs
507 -- TODO (can't be bothered right now)
509 -- erase reg->reg moves where the source and destination are the same.
510 -- If the src temp didn't die in this instr but happened to be allocated
511 -- to the same real reg as the destination, then we can erase the move anyway.
512 squashed_instr = case isRegRegMove patched_instr of
517 return (squashed_instr ++ w_spills ++ reverse r_spills
518 ++ clobber_saves ++ new_instrs,
522 -- -----------------------------------------------------------------------------
525 releaseRegs regs = do
530 loop assig free _ | free `seq` False = undefined
531 loop assig free [] = do setAssigR assig; setFreeRegsR free; return ()
532 loop assig free (RealReg r : rs) = loop assig (releaseReg r free) rs
533 loop assig free (r:rs) =
534 case lookupUFM assig r of
535 Just (InBoth real _) -> loop (delFromUFM assig r) (releaseReg real free) rs
536 Just (InReg real) -> loop (delFromUFM assig r) (releaseReg real free) rs
537 _other -> loop (delFromUFM assig r) free rs
539 -- -----------------------------------------------------------------------------
540 -- Clobber real registers
543 For each temp in a register that is going to be clobbered:
544 - if the temp dies after this instruction, do nothing
545 - otherwise, put it somewhere safe (another reg if possible,
546 otherwise spill and record InBoth in the assignment).
548 for allocateRegs on the temps *read*,
549 - clobbered regs are allocatable.
551 for allocateRegs on the temps *written*,
552 - clobbered regs are not allocatable.
556 :: [RegNo] -- real registers clobbered by this instruction
557 -> [Reg] -- registers which are no longer live after this insn
558 -> RegM [Instr] -- return: instructions to spill any temps that will
561 saveClobberedTemps [] _ = return [] -- common case
562 saveClobberedTemps clobbered dying = do
565 to_spill = [ (temp,reg) | (temp, InReg reg) <- ufmToList assig,
566 reg `elem` clobbered,
567 temp `notElem` map getUnique dying ]
569 (instrs,assig') <- clobber assig [] to_spill
573 clobber assig instrs [] = return (instrs,assig)
574 clobber assig instrs ((temp,reg):rest)
576 --ToDo: copy it to another register if possible
577 (spill,slot) <- spillR (RealReg reg) temp
578 recordSpill (SpillClobber temp)
580 let new_assign = addToUFM assig temp (InBoth reg slot)
581 clobber new_assign (spill : COMMENT FSLIT("spill clobber") : instrs) rest
583 clobberRegs :: [RegNo] -> RegM ()
584 clobberRegs [] = return () -- common case
585 clobberRegs clobbered = do
586 freeregs <- getFreeRegsR
587 setFreeRegsR $! foldr allocateReg freeregs clobbered
589 setAssigR $! clobber assig (ufmToList assig)
591 -- if the temp was InReg and clobbered, then we will have
592 -- saved it in saveClobberedTemps above. So the only case
593 -- we have to worry about here is InBoth. Note that this
594 -- also catches temps which were loaded up during allocation
595 -- of read registers, not just those saved in saveClobberedTemps.
596 clobber assig [] = assig
597 clobber assig ((temp, InBoth reg slot) : rest)
598 | reg `elem` clobbered
599 = clobber (addToUFM assig temp (InMem slot)) rest
600 clobber assig (entry:rest)
603 -- -----------------------------------------------------------------------------
604 -- allocateRegsAndSpill
606 -- This function does several things:
607 -- For each temporary referred to by this instruction,
608 -- we allocate a real register (spilling another temporary if necessary).
609 -- We load the temporary up from memory if necessary.
610 -- We also update the register assignment in the process, and
611 -- the list of free registers and free stack slots.
614 :: Bool -- True <=> reading (load up spilled regs)
615 -> [Reg] -- don't push these out
616 -> [Instr] -- spill insns
617 -> [RegNo] -- real registers allocated (accum.)
618 -> [Reg] -- temps to allocate
619 -> RegM ([Instr], [RegNo])
621 allocateRegsAndSpill reading keep spills alloc []
622 = return (spills,reverse alloc)
624 allocateRegsAndSpill reading keep spills alloc (r:rs) = do
626 case lookupUFM assig r of
627 -- case (1a): already in a register
628 Just (InReg my_reg) ->
629 allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
631 -- case (1b): already in a register (and memory)
632 -- NB1. if we're writing this register, update its assignemnt to be
633 -- InReg, because the memory value is no longer valid.
634 -- NB2. This is why we must process written registers here, even if they
635 -- are also read by the same instruction.
636 Just (InBoth my_reg mem) -> do
637 when (not reading) (setAssigR (addToUFM assig r (InReg my_reg)))
638 allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
640 -- Not already in a register, so we need to find a free one...
642 freeregs <- getFreeRegsR
644 case getFreeRegs (regClass r) freeregs of
646 -- case (2): we have a free register
648 spills' <- loadTemp reading r loc my_reg spills
650 | Just (InMem slot) <- loc, reading = InBoth my_reg slot
651 | otherwise = InReg my_reg
652 setAssigR (addToUFM assig r $! new_loc)
653 setFreeRegsR (allocateReg my_reg freeregs)
654 allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
656 -- case (3): we need to push something out to free up a register
659 keep' = map getUnique keep
660 candidates1 = [ (temp,reg,mem)
661 | (temp, InBoth reg mem) <- ufmToList assig,
662 temp `notElem` keep', regClass (RealReg reg) == regClass r ]
663 candidates2 = [ (temp,reg)
664 | (temp, InReg reg) <- ufmToList assig,
665 temp `notElem` keep', regClass (RealReg reg) == regClass r ]
667 ASSERT2(not (null candidates1 && null candidates2),
668 text (show freeregs) <+> ppr r <+> ppr assig) do
672 -- we have a temporary that is in both register and mem,
673 -- just free up its register for use.
675 (temp,my_reg,slot):_ -> do
676 spills' <- loadTemp reading r loc my_reg spills
678 assig1 = addToUFM assig temp (InMem slot)
679 assig2 = addToUFM assig1 r (InReg my_reg)
682 allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
684 -- otherwise, we need to spill a temporary that currently
685 -- resides in a register.
690 -- TODO: plenty of room for optimisation in choosing which temp
691 -- to spill. We just pick the first one that isn't used in
692 -- the current instruction for now.
694 let (temp_to_push_out, my_reg) = myHead "regalloc" candidates2
696 (spill_insn, slot) <- spillR (RealReg my_reg) temp_to_push_out
697 let spill_store = (if reading then id else reverse)
698 [ COMMENT FSLIT("spill alloc")
701 -- record that this temp was spilled
702 recordSpill (SpillAlloc temp_to_push_out)
704 -- update the register assignment
705 let assig1 = addToUFM assig temp_to_push_out (InMem slot)
706 let assig2 = addToUFM assig1 r (InReg my_reg)
709 -- if need be, load up a spilled temp into the reg we've just freed up.
710 spills' <- loadTemp reading r loc my_reg spills
712 allocateRegsAndSpill reading keep
713 (spill_store ++ spills')
717 -- | Load up a spilled temporary if we need to.
720 -> Reg -- the temp being loaded
721 -> Maybe Loc -- the current location of this temp
722 -> RegNo -- the hreg to load the temp into
726 loadTemp True vreg (Just (InMem slot)) hreg spills
728 insn <- loadR (RealReg hreg) slot
729 recordSpill (SpillLoad $ getUnique vreg)
730 return $ COMMENT FSLIT("spill load") : insn : spills
732 loadTemp _ _ _ _ spills =
736 myHead s [] = panic s
739 -- -----------------------------------------------------------------------------
740 -- Joining a jump instruction to its targets
742 -- The first time we encounter a jump to a particular basic block, we
743 -- record the assignment of temporaries. The next time we encounter a
744 -- jump to the same block, we compare our current assignment to the
745 -- stored one. They might be different if spilling has occrred in one
746 -- branch; so some fixup code will be required to match up the
754 -> RegM ([NatBasicBlock], Instr)
756 joinToTargets block_live new_blocks instr []
757 = return (new_blocks, instr)
759 joinToTargets block_live new_blocks instr (dest:dests) = do
760 block_assig <- getBlockAssigR
763 -- adjust the assignment to remove any registers which are not
764 -- live on entry to the destination block.
765 adjusted_assig = filterUFM_Directly still_live assig
767 live_set = lookItUp "joinToTargets" block_live dest
768 still_live uniq _ = uniq `elemUniqSet_Directly` live_set
770 -- and free up those registers which are now free.
772 [ r | (reg, loc) <- ufmToList assig,
773 not (elemUniqSet_Directly reg live_set),
776 regsOfLoc (InReg r) = [r]
777 regsOfLoc (InBoth r _) = [r]
778 regsOfLoc (InMem _) = []
780 case lookupUFM block_assig dest of
781 -- Nothing <=> this is the first time we jumped to this
784 freeregs <- getFreeRegsR
785 let freeregs' = foldr releaseReg freeregs to_free
786 setBlockAssigR (addToUFM block_assig dest
787 (freeregs',adjusted_assig))
788 joinToTargets block_live new_blocks instr dests
790 Just (freeregs,dest_assig)
792 -- the assignments match
793 | ufmToList dest_assig == ufmToList adjusted_assig
794 -> joinToTargets block_live new_blocks instr dests
801 let graph = makeRegMovementGraph adjusted_assig dest_assig
802 let sccs = stronglyConnCompR graph
803 fixUpInstrs <- mapM (handleComponent delta instr) sccs
805 block_id <- getUniqueR
806 let block = BasicBlock (BlockId block_id) $
807 concat fixUpInstrs ++ mkBranchInstr dest
809 let instr' = patchJump instr dest (BlockId block_id)
811 joinToTargets block_live (block : new_blocks) instr' dests
814 -- | Construct a graph of register/spill movements.
816 -- We cut some corners by
817 -- a) not handling cyclic components
818 -- b) not handling memory-to-memory moves.
820 -- Cyclic components seem to occur only very rarely,
821 -- and we don't need memory-to-memory moves because we
822 -- make sure that every temporary always gets its own
825 makeRegMovementGraph :: RegMap Loc -> RegMap Loc -> [(Unique, Loc, [Loc])]
826 makeRegMovementGraph adjusted_assig dest_assig
829 = expandNode vreg src
830 $ lookupWithDefaultUFM_Directly
832 (panic "RegisterAlloc.joinToTargets")
835 in [ node | (vreg, src) <- ufmToList adjusted_assig
836 , node <- mkNodes src vreg ]
838 -- The InBoth handling is a little tricky here. If
839 -- the destination is InBoth, then we must ensure that
840 -- the value ends up in both locations. An InBoth
841 -- destination must conflict with an InReg or InMem
842 -- source, so we expand an InBoth destination as
843 -- necessary. An InBoth source is slightly different:
844 -- we only care about the register that the source value
845 -- is in, so that we can move it to the destinations.
847 expandNode vreg loc@(InReg src) (InBoth dst mem)
848 | src == dst = [(vreg, loc, [InMem mem])]
849 | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
851 expandNode vreg loc@(InMem src) (InBoth dst mem)
852 | src == mem = [(vreg, loc, [InReg dst])]
853 | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
855 expandNode vreg loc@(InBoth _ src) (InMem dst)
856 | src == dst = [] -- guaranteed to be true
858 expandNode vreg loc@(InBoth src _) (InReg dst)
861 expandNode vreg loc@(InBoth src _) dst
862 = expandNode vreg (InReg src) dst
864 expandNode vreg src dst
866 | otherwise = [(vreg, src, [dst])]
869 -- | Make a move instruction between these two locations so we
870 -- can join together allocations for different basic blocks.
872 makeMove :: Int -> Unique -> Loc -> Loc -> RegM Instr
873 makeMove delta vreg (InReg src) (InReg dst)
874 = do recordSpill (SpillJoinRR vreg)
875 return $ mkRegRegMoveInstr (RealReg src) (RealReg dst)
877 makeMove delta vreg (InMem src) (InReg dst)
878 = do recordSpill (SpillJoinRM vreg)
879 return $ mkLoadInstr (RealReg dst) delta src
881 makeMove delta vreg (InReg src) (InMem dst)
882 = do recordSpill (SpillJoinRM vreg)
883 return $ mkSpillInstr (RealReg src) delta dst
885 makeMove delta vreg src dst
886 = panic $ "makeMove " ++ show vreg ++ " (" ++ show src ++ ") ("
888 ++ " (workaround: use -fviaC)"
891 -- we have eliminated any possibility of single-node cylces
892 -- in expandNode above.
893 handleComponent :: Int -> Instr -> SCC (Unique, Loc, [Loc]) -> RegM [Instr]
894 handleComponent delta instr (AcyclicSCC (vreg,src,dsts))
895 = mapM (makeMove delta vreg src) dsts
897 -- we can not have cycles that involve memory
898 -- locations as source nor as single destination
899 -- because memory locations (stack slots) are
900 -- allocated exclusively for a virtual register and
901 -- therefore can not require a fixup
902 handleComponent delta instr (CyclicSCC ((vreg,src@(InReg sreg),dsts):rest))
904 spill_id <- getUniqueR
905 (saveInstr,slot) <- spillR (RealReg sreg) spill_id
906 remainingFixUps <- mapM (handleComponent delta instr) (stronglyConnCompR rest)
907 restoreAndFixInstr <- getRestoreMoves dsts slot
908 return ([instr] ++ concat remainingFixUps ++ restoreAndFixInstr)
911 getRestoreMoves [r@(InReg reg), mem@(InMem _)] slot
913 restoreToReg <- loadR (RealReg reg) slot
914 moveInstr <- makeMove delta vreg r mem
915 return $ [COMMENT FSLIT("spill join move"), restoreToReg, moveInstr]
917 getRestoreMoves [InReg reg] slot
918 = loadR (RealReg reg) slot >>= return . (:[])
920 getRestoreMoves [InMem _] _ = panic "getRestoreMoves can not handle memory only restores"
921 getRestoreMoves _ _ = panic "getRestoreMoves unknown case"
924 handleComponent delta instr (CyclicSCC _)
925 = panic "Register Allocator: handleComponent cyclic"
929 -- -----------------------------------------------------------------------------
930 -- The register allocator's monad.
932 -- Here we keep all the state that the register allocator keeps track
933 -- of as it walks the instructions in a basic block.
937 ra_blockassig :: BlockAssignment,
938 -- The current mapping from basic blocks to
939 -- the register assignments at the beginning of that block.
940 ra_freeregs :: {-#UNPACK#-}!FreeRegs, -- free machine registers
941 ra_assig :: RegMap Loc, -- assignment of temps to locations
942 ra_delta :: Int, -- current stack delta
943 ra_stack :: StackMap, -- free stack slots for spilling
944 ra_us :: UniqSupply, -- unique supply for generating names
947 -- Record why things were spilled, for -ddrop-asm-stats.
948 -- Just keep a list here instead of a map of regs -> reasons.
949 -- We don't want to slow down the allocator if we're not going to emit the stats.
950 ra_spills :: [SpillReason]
953 newtype RegM a = RegM { unReg :: RA_State -> (# RA_State, a #) }
956 instance Monad RegM where
957 m >>= k = RegM $ \s -> case unReg m s of { (# s, a #) -> unReg (k a) s }
958 return a = RegM $ \s -> (# s, a #)
960 runR :: BlockAssignment -> FreeRegs -> RegMap Loc -> StackMap -> UniqSupply
961 -> RegM a -> (BlockAssignment, StackMap, RegAllocStats, a)
962 runR block_assig freeregs assig stack us thing =
963 case unReg thing (RA_State{ ra_blockassig=block_assig, ra_freeregs=freeregs,
964 ra_assig=assig, ra_delta=0{-???-}, ra_stack=stack,
965 ra_us = us, ra_spills = [] }) of
966 (# state'@RA_State{ ra_blockassig=block_assig, ra_stack=stack', ra_spills=spills' }, returned_thing #)
967 -> (block_assig, stack', makeRAStats state', returned_thing)
969 spillR :: Reg -> Unique -> RegM (Instr, Int)
970 spillR reg temp = RegM $ \ s@RA_State{ra_delta=delta, ra_stack=stack} ->
971 let (stack',slot) = getStackSlotFor stack temp
972 instr = mkSpillInstr reg delta slot
974 (# s{ra_stack=stack'}, (instr,slot) #)
976 loadR :: Reg -> Int -> RegM Instr
977 loadR reg slot = RegM $ \ s@RA_State{ra_delta=delta} ->
978 (# s, mkLoadInstr reg delta slot #)
980 getFreeRegsR :: RegM FreeRegs
981 getFreeRegsR = RegM $ \ s@RA_State{ra_freeregs = freeregs} ->
984 setFreeRegsR :: FreeRegs -> RegM ()
985 setFreeRegsR regs = RegM $ \ s ->
986 (# s{ra_freeregs = regs}, () #)
988 getAssigR :: RegM (RegMap Loc)
989 getAssigR = RegM $ \ s@RA_State{ra_assig = assig} ->
992 setAssigR :: RegMap Loc -> RegM ()
993 setAssigR assig = RegM $ \ s ->
994 (# s{ra_assig=assig}, () #)
996 getBlockAssigR :: RegM BlockAssignment
997 getBlockAssigR = RegM $ \ s@RA_State{ra_blockassig = assig} ->
1000 setBlockAssigR :: BlockAssignment -> RegM ()
1001 setBlockAssigR assig = RegM $ \ s ->
1002 (# s{ra_blockassig = assig}, () #)
1004 setDeltaR :: Int -> RegM ()
1005 setDeltaR n = RegM $ \ s ->
1006 (# s{ra_delta = n}, () #)
1008 getDeltaR :: RegM Int
1009 getDeltaR = RegM $ \s -> (# s, ra_delta s #)
1011 getUniqueR :: RegM Unique
1012 getUniqueR = RegM $ \s ->
1013 case splitUniqSupply (ra_us s) of
1014 (us1, us2) -> (# s{ra_us = us2}, uniqFromSupply us1 #)
1016 -- | Record that a spill instruction was inserted, for profiling.
1017 recordSpill :: SpillReason -> RegM ()
1019 = RegM $ \s -> (# s { ra_spills = spill : ra_spills s}, () #)
1021 -- -----------------------------------------------------------------------------
1023 -- | Reasons why instructions might be inserted by the spiller.
1024 -- Used when generating stats for -ddrop-asm-stats.
1027 = SpillAlloc !Unique -- ^ vreg was spilled to a slot so we could use its
1028 -- current hreg for another vreg
1029 | SpillClobber !Unique -- ^ vreg was moved because its hreg was clobbered
1030 | SpillLoad !Unique -- ^ vreg was loaded from a spill slot
1032 | SpillJoinRR !Unique -- ^ reg-reg move inserted during join to targets
1033 | SpillJoinRM !Unique -- ^ reg-mem move inserted during join to targets
1036 -- | Used to carry interesting stats out of the register allocator.
1039 { ra_spillInstrs :: UniqFM [Int] }
1042 -- | Make register allocator stats from its final state.
1043 makeRAStats :: RA_State -> RegAllocStats
1046 { ra_spillInstrs = binSpillReasons (ra_spills state) }
1049 -- | Build a map of how many times each reg was alloced, clobbered, loaded etc.
1051 :: [SpillReason] -> UniqFM [Int]
1053 binSpillReasons reasons
1057 (map (\reason -> case reason of
1058 SpillAlloc r -> (r, [1, 0, 0, 0, 0])
1059 SpillClobber r -> (r, [0, 1, 0, 0, 0])
1060 SpillLoad r -> (r, [0, 0, 1, 0, 0])
1061 SpillJoinRR r -> (r, [0, 0, 0, 1, 0])
1062 SpillJoinRM r -> (r, [0, 0, 0, 0, 1])) reasons)
1065 -- | Count reg-reg moves remaining in this code.
1066 countRegRegMovesNat :: NatCmmTop -> Int
1067 countRegRegMovesNat cmm
1068 = execState (mapGenBlockTopM countBlock cmm) 0
1070 countBlock b@(BasicBlock i instrs)
1071 = do instrs' <- mapM countInstr instrs
1075 | Just _ <- isRegRegMove instr
1083 -- | Pretty print some RegAllocStats
1084 pprStats :: [NatCmmTop] -> [RegAllocStats] -> SDoc
1085 pprStats code statss
1086 = let -- sum up all the instrs inserted by the spiller
1087 spills = foldl' (plusUFM_C (zipWith (+)))
1089 $ map ra_spillInstrs statss
1091 spillTotals = foldl' (zipWith (+))
1095 -- count how many reg-reg-moves remain in the code
1096 moves = sum $ map countRegRegMovesNat code
1098 pprSpill (reg, spills)
1099 = parens $ (hcat $ punctuate (text ", ") (doubleQuotes (ppr reg) : map ppr spills))
1101 in ( text "-- spills-added-total"
1102 $$ text "-- (allocs, clobbers, loads, joinRR, joinRM, reg_reg_moves_remaining)"
1103 $$ (parens $ (hcat $ punctuate (text ", ") (map ppr spillTotals ++ [ppr moves])))
1105 $$ text "-- spills-added"
1106 $$ text "-- (reg_name, allocs, clobbers, loads, joinRR, joinRM)"
1107 $$ (vcat $ map pprSpill
1112 -- -----------------------------------------------------------------------------
1116 my_fromJust s p Nothing = pprPanic ("fromJust: " ++ s) p
1117 my_fromJust s p (Just x) = x
1119 my_fromJust _ _ = fromJust
1122 lookItUp :: Uniquable b => String -> UniqFM a -> b -> a
1123 lookItUp str fm x = my_fromJust str (ppr (getUnique x)) (lookupUFM fm x)