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 (
87 #include "HsVersions.h"
96 import Unique ( Uniquable(getUnique), Unique )
103 import Data.Maybe ( fromJust )
105 import Data.List ( nub, partition, mapAccumL)
106 import Control.Monad ( when )
111 -- -----------------------------------------------------------------------------
112 -- The free register set
114 -- This needs to be *efficient*
116 {- Here's an inefficient 'executable specification' of the FreeRegs data type:
117 type FreeRegs = [RegNo]
120 releaseReg n f = if n `elem` f then f else (n : f)
121 initFreeRegs = allocatableRegs
122 getFreeRegs cls f = filter ( (==cls) . regClass . RealReg ) f
123 allocateReg f r = filter (/= r) f
126 #if defined(powerpc_TARGET_ARCH)
128 -- The PowerPC has 32 integer and 32 floating point registers.
129 -- This is 32bit PowerPC, so Word64 is inefficient - two Word32s are much
131 -- Note that when getFreeRegs scans for free registers, it starts at register
132 -- 31 and counts down. This is a hack for the PowerPC - the higher-numbered
133 -- registers are callee-saves, while the lower regs are caller-saves, so it
134 -- makes sense to start at the high end.
135 -- Apart from that, the code does nothing PowerPC-specific, so feel free to
136 -- add your favourite platform to the #if (if you have 64 registers but only
139 data FreeRegs = FreeRegs !Word32 !Word32
140 deriving( Show ) -- The Show is used in an ASSERT
142 noFreeRegs :: FreeRegs
143 noFreeRegs = FreeRegs 0 0
145 releaseReg :: RegNo -> FreeRegs -> FreeRegs
146 releaseReg r (FreeRegs g f)
147 | r > 31 = FreeRegs g (f .|. (1 `shiftL` (fromIntegral r - 32)))
148 | otherwise = FreeRegs (g .|. (1 `shiftL` fromIntegral r)) f
150 initFreeRegs :: FreeRegs
151 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
153 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
154 getFreeRegs cls (FreeRegs g f)
155 | RcDouble <- cls = go f (0x80000000) 63
156 | RcInteger <- cls = go g (0x80000000) 31
159 go x m i | x .&. m /= 0 = i : (go x (m `shiftR` 1) $! i-1)
160 | otherwise = go x (m `shiftR` 1) $! i-1
162 allocateReg :: RegNo -> FreeRegs -> FreeRegs
163 allocateReg r (FreeRegs g f)
164 | r > 31 = FreeRegs g (f .&. complement (1 `shiftL` (fromIntegral r - 32)))
165 | otherwise = FreeRegs (g .&. complement (1 `shiftL` fromIntegral r)) f
169 -- If we have less than 32 registers, or if we have efficient 64-bit words,
170 -- we will just use a single bitfield.
172 #if defined(alpha_TARGET_ARCH)
173 type FreeRegs = Word64
175 type FreeRegs = Word32
178 noFreeRegs :: FreeRegs
181 releaseReg :: RegNo -> FreeRegs -> FreeRegs
182 releaseReg n f = f .|. (1 `shiftL` n)
184 initFreeRegs :: FreeRegs
185 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
187 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
188 getFreeRegs cls f = go f 0
191 | n .&. 1 /= 0 && regClass (RealReg m) == cls
192 = m : (go (n `shiftR` 1) $! (m+1))
194 = go (n `shiftR` 1) $! (m+1)
195 -- ToDo: there's no point looking through all the integer registers
196 -- in order to find a floating-point one.
198 allocateReg :: RegNo -> FreeRegs -> FreeRegs
199 allocateReg r f = f .&. complement (1 `shiftL` fromIntegral r)
203 -- -----------------------------------------------------------------------------
204 -- The assignment of virtual registers to stack slots
206 -- We have lots of stack slots. Memory-to-memory moves are a pain on most
207 -- architectures. Therefore, we avoid having to generate memory-to-memory moves
208 -- by simply giving every virtual register its own stack slot.
210 -- The StackMap stack map keeps track of virtual register - stack slot
211 -- associations and of which stack slots are still free. Once it has been
212 -- associated, a stack slot is never "freed" or removed from the StackMap again,
213 -- it remains associated until we are done with the current CmmProc.
216 data StackMap = StackMap [StackSlot] (UniqFM StackSlot)
218 emptyStackMap :: StackMap
219 emptyStackMap = StackMap [0..maxSpillSlots] emptyUFM
221 getStackSlotFor :: StackMap -> Unique -> (StackMap,Int)
222 getStackSlotFor fs@(StackMap [] reserved) reg
223 = panic "RegAllocLinear.getStackSlotFor: out of stack slots"
224 getStackSlotFor fs@(StackMap (freeSlot:stack') reserved) reg =
225 case lookupUFM reserved reg of
226 Just slot -> (fs,slot)
227 Nothing -> (StackMap stack' (addToUFM reserved reg freeSlot), freeSlot)
229 -- -----------------------------------------------------------------------------
230 -- Top level of the register allocator
232 -- Allocate registers
237 regAlloc cmm@(CmmData sec d)
238 = returnUs $ CmmData sec d
240 regAlloc cmm@(CmmProc (LiveInfo info _ _) lbl params [])
241 = returnUs $ CmmProc info lbl params []
243 regAlloc cmm@(CmmProc (LiveInfo info (Just first_id) block_live) lbl params comps)
244 = let ann_sccs = map (\b -> case b of
245 BasicBlock i [b] -> AcyclicSCC b
246 BasicBlock i bs -> CyclicSCC bs)
249 in linearRegAlloc block_live ann_sccs `thenUs` \final_blocks ->
251 let ((first':_), rest') = partition ((== first_id) . blockId) final_blocks
252 in returnUs $ CmmProc info lbl params (first' : rest')
256 -- -----------------------------------------------------------------------------
257 -- Linear sweep to allocate registers
259 data Loc = InReg {-# UNPACK #-} !RegNo
260 | InMem {-# UNPACK #-} !Int -- stack slot
261 | InBoth {-# UNPACK #-} !RegNo
262 {-# UNPACK #-} !Int -- stack slot
263 deriving (Eq, Show, Ord)
266 A temporary can be marked as living in both a register and memory
267 (InBoth), for example if it was recently loaded from a spill location.
268 This makes it cheap to spill (no save instruction required), but we
269 have to be careful to turn this into InReg if the value in the
272 This is also useful when a temporary is about to be clobbered. We
273 save it in a spill location, but mark it as InBoth because the current
274 instruction might still want to read it.
278 instance Outputable Loc where
279 ppr l = text (show l)
283 :: BlockMap RegSet -- live regs on entry to each basic block
284 -> [SCC LiveBasicBlock] -- instructions annotated with "deaths"
285 -> UniqSM [NatBasicBlock]
286 linearRegAlloc block_live sccs = linearRA_SCCs emptyBlockMap emptyStackMap sccs
291 -> [SCC LiveBasicBlock]
292 -> UniqSM [NatBasicBlock]
293 linearRA_SCCs block_assig stack [] = returnUs []
294 linearRA_SCCs block_assig stack
295 (AcyclicSCC (BasicBlock id instrs) : sccs)
296 = getUs `thenUs` \us ->
298 (block_assig',stack',(instrs',fixups)) =
299 case lookupUFM block_assig id of
300 -- no prior info about this block: assume everything is
301 -- free and the assignment is empty.
303 runR block_assig initFreeRegs
304 emptyRegMap stack us $
305 linearRA [] [] instrs
306 Just (freeregs,assig) ->
307 runR block_assig freeregs assig stack us $
308 linearRA [] [] instrs
310 linearRA_SCCs block_assig' stack' sccs `thenUs` \moreBlocks ->
311 returnUs $ BasicBlock id instrs' : fixups ++ moreBlocks
313 linearRA_SCCs block_assig stack
314 (CyclicSCC blocks : sccs)
315 = getUs `thenUs` \us ->
317 ((block_assig', stack', _), blocks') = mapAccumL processBlock
318 (block_assig, stack, us)
321 linearRA_SCCs block_assig' stack' sccs `thenUs` \moreBlocks ->
322 returnUs $ concat blocks' ++ moreBlocks
324 processBlock (block_assig, stack, us0) (BasicBlock id instrs)
325 = ((block_assig', stack', us'), BasicBlock id instrs' : fixups)
327 (us, us') = splitUniqSupply us0
328 (block_assig',stack',(instrs',fixups)) =
329 case lookupUFM block_assig id of
330 -- no prior info about this block: assume everything is
331 -- free and the assignment is empty.
333 runR block_assig initFreeRegs
334 emptyRegMap stack us $
335 linearRA [] [] instrs
336 Just (freeregs,assig) ->
337 runR block_assig freeregs assig stack us $
338 linearRA [] [] instrs
340 linearRA :: [Instr] -> [NatBasicBlock] -> [LiveInstr]
341 -> RegM ([Instr], [NatBasicBlock])
342 linearRA instr_acc fixups [] =
343 return (reverse instr_acc, fixups)
344 linearRA instr_acc fixups (instr:instrs) = do
345 (instr_acc', new_fixups) <- raInsn block_live instr_acc instr
346 linearRA instr_acc' (new_fixups++fixups) instrs
348 -- -----------------------------------------------------------------------------
349 -- Register allocation for a single instruction
351 type BlockAssignment = BlockMap (FreeRegs, RegMap Loc)
353 raInsn :: BlockMap RegSet -- Live temporaries at each basic block
354 -> [Instr] -- new instructions (accum.)
355 -> LiveInstr -- the instruction (with "deaths")
357 [Instr], -- new instructions
358 [NatBasicBlock] -- extra fixup blocks
361 raInsn block_live new_instrs (Instr instr@(COMMENT _) Nothing)
362 = return (new_instrs, [])
364 raInsn block_live new_instrs (Instr instr@(DELTA n) Nothing)
367 return (new_instrs, [])
369 raInsn block_live new_instrs (Instr instr (Just live))
373 -- If we have a reg->reg move between virtual registers, where the
374 -- src register is not live after this instruction, and the dst
375 -- register does not already have an assignment,
376 -- and the source register is assigned to a register, not to a spill slot,
377 -- then we can eliminate the instruction.
378 -- (we can't eliminitate it if the source register is on the stack, because
379 -- we do not want to use one spill slot for different virtual registers)
380 case isRegRegMove instr of
381 Just (src,dst) | src `elementOfUniqSet` (liveDieRead live),
383 not (dst `elemUFM` assig),
384 Just (InReg _) <- (lookupUFM assig src) -> do
386 RealReg i -> setAssigR (addToUFM assig dst (InReg i))
387 -- if src is a fixed reg, then we just map dest to this
388 -- reg in the assignment. src must be an allocatable reg,
389 -- otherwise it wouldn't be in r_dying.
390 _virt -> case lookupUFM assig src of
391 Nothing -> panic "raInsn"
393 setAssigR (addToUFM (delFromUFM assig src) dst loc)
395 -- we have elimianted this instruction
397 freeregs <- getFreeRegsR
399 pprTrace "raInsn" (text "ELIMINATED: " <> docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ text (show freeregs) $$ ppr assig) $ do
401 return (new_instrs, [])
403 other -> genRaInsn block_live new_instrs instr
404 (uniqSetToList $ liveDieRead live)
405 (uniqSetToList $ liveDieWrite live)
408 raInsn block_live new_instrs li
409 = pprPanic "raInsn" (text "no match for:" <> ppr li)
412 genRaInsn block_live new_instrs instr r_dying w_dying =
413 case regUsage instr of { RU read written ->
414 case partition isRealReg written of { (real_written1,virt_written) ->
417 real_written = [ r | RealReg r <- real_written1 ]
419 -- we don't need to do anything with real registers that are
420 -- only read by this instr. (the list is typically ~2 elements,
421 -- so using nub isn't a problem).
422 virt_read = nub (filter isVirtualReg read)
425 -- (a) save any temporaries which will be clobbered by this instruction
426 clobber_saves <- saveClobberedTemps real_written r_dying
429 freeregs <- getFreeRegsR
431 pprTrace "raInsn" (docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ ppr virt_read <+> ppr virt_written $$ text (show freeregs) $$ ppr assig) $ do
434 -- (b), (c) allocate real regs for all regs read by this instruction.
435 (r_spills, r_allocd) <-
436 allocateRegsAndSpill True{-reading-} virt_read [] [] virt_read
438 -- (d) Update block map for new destinations
439 -- NB. do this before removing dead regs from the assignment, because
440 -- these dead regs might in fact be live in the jump targets (they're
441 -- only dead in the code that follows in the current basic block).
442 (fixup_blocks, adjusted_instr)
443 <- joinToTargets block_live [] instr (jumpDests instr [])
445 -- (e) Delete all register assignments for temps which are read
446 -- (only) and die here. Update the free register list.
449 -- (f) Mark regs which are clobbered as unallocatable
450 clobberRegs real_written
452 -- (g) Allocate registers for temporaries *written* (only)
453 (w_spills, w_allocd) <-
454 allocateRegsAndSpill False{-writing-} virt_written [] [] virt_written
456 -- (h) Release registers for temps which are written here and not
461 -- (i) Patch the instruction
462 patch_map = listToUFM [ (t,RealReg r) |
463 (t,r) <- zip virt_read r_allocd
464 ++ zip virt_written w_allocd ]
466 patched_instr = patchRegs adjusted_instr patchLookup
467 patchLookup x = case lookupUFM patch_map x of
472 -- pprTrace "patched" (docToSDoc (pprInstr patched_instr)) $ do
474 -- (j) free up stack slots for dead spilled regs
475 -- TODO (can't be bothered right now)
477 return (patched_instr : w_spills ++ reverse r_spills
478 ++ clobber_saves ++ new_instrs,
482 -- -----------------------------------------------------------------------------
485 releaseRegs regs = do
490 loop assig free _ | free `seq` False = undefined
491 loop assig free [] = do setAssigR assig; setFreeRegsR free; return ()
492 loop assig free (RealReg r : rs) = loop assig (releaseReg r free) rs
493 loop assig free (r:rs) =
494 case lookupUFM assig r of
495 Just (InBoth real _) -> loop (delFromUFM assig r) (releaseReg real free) rs
496 Just (InReg real) -> loop (delFromUFM assig r) (releaseReg real free) rs
497 _other -> loop (delFromUFM assig r) free rs
499 -- -----------------------------------------------------------------------------
500 -- Clobber real registers
503 For each temp in a register that is going to be clobbered:
504 - if the temp dies after this instruction, do nothing
505 - otherwise, put it somewhere safe (another reg if possible,
506 otherwise spill and record InBoth in the assignment).
508 for allocateRegs on the temps *read*,
509 - clobbered regs are allocatable.
511 for allocateRegs on the temps *written*,
512 - clobbered regs are not allocatable.
516 :: [RegNo] -- real registers clobbered by this instruction
517 -> [Reg] -- registers which are no longer live after this insn
518 -> RegM [Instr] -- return: instructions to spill any temps that will
521 saveClobberedTemps [] _ = return [] -- common case
522 saveClobberedTemps clobbered dying = do
525 to_spill = [ (temp,reg) | (temp, InReg reg) <- ufmToList assig,
526 reg `elem` clobbered,
527 temp `notElem` map getUnique dying ]
529 (instrs,assig') <- clobber assig [] to_spill
533 clobber assig instrs [] = return (instrs,assig)
534 clobber assig instrs ((temp,reg):rest)
536 --ToDo: copy it to another register if possible
537 (spill,slot) <- spillR (RealReg reg) temp
538 clobber (addToUFM assig temp (InBoth reg slot)) (spill: COMMENT FSLIT("spill clobber") : instrs) rest
540 clobberRegs :: [RegNo] -> RegM ()
541 clobberRegs [] = return () -- common case
542 clobberRegs clobbered = do
543 freeregs <- getFreeRegsR
544 setFreeRegsR $! foldr allocateReg freeregs clobbered
546 setAssigR $! clobber assig (ufmToList assig)
548 -- if the temp was InReg and clobbered, then we will have
549 -- saved it in saveClobberedTemps above. So the only case
550 -- we have to worry about here is InBoth. Note that this
551 -- also catches temps which were loaded up during allocation
552 -- of read registers, not just those saved in saveClobberedTemps.
553 clobber assig [] = assig
554 clobber assig ((temp, InBoth reg slot) : rest)
555 | reg `elem` clobbered
556 = clobber (addToUFM assig temp (InMem slot)) rest
557 clobber assig (entry:rest)
560 -- -----------------------------------------------------------------------------
561 -- allocateRegsAndSpill
563 -- This function does several things:
564 -- For each temporary referred to by this instruction,
565 -- we allocate a real register (spilling another temporary if necessary).
566 -- We load the temporary up from memory if necessary.
567 -- We also update the register assignment in the process, and
568 -- the list of free registers and free stack slots.
571 :: Bool -- True <=> reading (load up spilled regs)
572 -> [Reg] -- don't push these out
573 -> [Instr] -- spill insns
574 -> [RegNo] -- real registers allocated (accum.)
575 -> [Reg] -- temps to allocate
576 -> RegM ([Instr], [RegNo])
578 allocateRegsAndSpill reading keep spills alloc []
579 = return (spills,reverse alloc)
581 allocateRegsAndSpill reading keep spills alloc (r:rs) = do
583 case lookupUFM assig r of
584 -- case (1a): already in a register
585 Just (InReg my_reg) ->
586 allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
588 -- case (1b): already in a register (and memory)
589 -- NB1. if we're writing this register, update its assignemnt to be
590 -- InReg, because the memory value is no longer valid.
591 -- NB2. This is why we must process written registers here, even if they
592 -- are also read by the same instruction.
593 Just (InBoth my_reg mem) -> do
594 when (not reading) (setAssigR (addToUFM assig r (InReg my_reg)))
595 allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
597 -- Not already in a register, so we need to find a free one...
599 freeregs <- getFreeRegsR
601 case getFreeRegs (regClass r) freeregs of
603 -- case (2): we have a free register
605 spills' <- do_load reading loc my_reg spills
607 | Just (InMem slot) <- loc, reading = InBoth my_reg slot
608 | otherwise = InReg my_reg
609 setAssigR (addToUFM assig r $! new_loc)
610 setFreeRegsR (allocateReg my_reg freeregs)
611 allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
613 -- case (3): we need to push something out to free up a register
616 keep' = map getUnique keep
617 candidates1 = [ (temp,reg,mem)
618 | (temp, InBoth reg mem) <- ufmToList assig,
619 temp `notElem` keep', regClass (RealReg reg) == regClass r ]
620 candidates2 = [ (temp,reg)
621 | (temp, InReg reg) <- ufmToList assig,
622 temp `notElem` keep', regClass (RealReg reg) == regClass r ]
624 ASSERT2(not (null candidates1 && null candidates2),
625 text (show freeregs) <+> ppr r <+> ppr assig) do
629 -- we have a temporary that is in both register and mem,
630 -- just free up its register for use.
632 (temp,my_reg,slot):_ -> do
633 spills' <- do_load reading loc my_reg spills
635 assig1 = addToUFM assig temp (InMem slot)
636 assig2 = addToUFM assig1 r (InReg my_reg)
639 allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
641 -- otherwise, we need to spill a temporary that currently
642 -- resides in a register.
645 (temp_to_push_out, my_reg) = myHead "regalloc" candidates2
646 -- TODO: plenty of room for optimisation in choosing which temp
647 -- to spill. We just pick the first one that isn't used in
648 -- the current instruction for now.
650 (spill_insn,slot) <- spillR (RealReg my_reg) temp_to_push_out
652 assig1 = addToUFM assig temp_to_push_out (InMem slot)
653 assig2 = addToUFM assig1 r (InReg my_reg)
656 spills' <- do_load reading loc my_reg spills
657 allocateRegsAndSpill reading keep
658 (spill_insn : COMMENT FSLIT("spill alloc") : spills')
661 -- load up a spilled temporary if we need to
662 do_load True (Just (InMem slot)) reg spills = do
663 insn <- loadR (RealReg reg) slot
664 return (insn : COMMENT FSLIT("spill load") : spills)
665 do_load _ _ _ spills =
668 myHead s [] = panic s
671 -- -----------------------------------------------------------------------------
672 -- Joining a jump instruction to its targets
674 -- The first time we encounter a jump to a particular basic block, we
675 -- record the assignment of temporaries. The next time we encounter a
676 -- jump to the same block, we compare our current assignment to the
677 -- stored one. They might be different if spilling has occrred in one
678 -- branch; so some fixup code will be required to match up the
686 -> RegM ([NatBasicBlock], Instr)
688 joinToTargets block_live new_blocks instr []
689 = return (new_blocks, instr)
690 joinToTargets block_live new_blocks instr (dest:dests) = do
691 block_assig <- getBlockAssigR
694 -- adjust the assignment to remove any registers which are not
695 -- live on entry to the destination block.
696 adjusted_assig = filterUFM_Directly still_live assig
697 still_live uniq _ = uniq `elemUniqSet_Directly` live_set
699 -- and free up those registers which are now free.
701 [ r | (reg, loc) <- ufmToList assig,
702 not (elemUniqSet_Directly reg live_set),
705 regsOfLoc (InReg r) = [r]
706 regsOfLoc (InBoth r _) = [r]
707 regsOfLoc (InMem _) = []
709 case lookupUFM block_assig dest of
710 -- Nothing <=> this is the first time we jumped to this
713 freeregs <- getFreeRegsR
714 let freeregs' = foldr releaseReg freeregs to_free
715 setBlockAssigR (addToUFM block_assig dest
716 (freeregs',adjusted_assig))
717 joinToTargets block_live new_blocks instr dests
719 Just (freeregs,dest_assig)
720 | ufmToList dest_assig == ufmToList adjusted_assig
721 -> -- ok, the assignments match
722 joinToTargets block_live new_blocks instr dests
724 -> -- need fixup code
727 -- Construct a graph of register/spill movements and
728 -- untangle it component by component.
730 -- We cut some corners by
731 -- a) not handling cyclic components
732 -- b) not handling memory-to-memory moves.
734 -- Cyclic components seem to occur only very rarely,
735 -- and we don't need memory-to-memory moves because we
736 -- make sure that every temporary always gets its own
739 let graph = [ node | (vreg, src) <- ufmToList adjusted_assig,
740 node <- mkNodes src vreg ]
742 sccs = stronglyConnCompR graph
745 expandNode vreg src (lookupWithDefaultUFM_Directly
747 (panic "RegisterAlloc.joinToTargets")
750 -- The InBoth handling is a little tricky here. If
751 -- the destination is InBoth, then we must ensure that
752 -- the value ends up in both locations. An InBoth
753 -- destination must conflict with an InReg or InMem
754 -- source, so we expand an InBoth destination as
755 -- necessary. An InBoth source is slightly different:
756 -- we only care about the register that the source value
757 -- is in, so that we can move it to the destinations.
759 expandNode vreg loc@(InReg src) (InBoth dst mem)
760 | src == dst = [(vreg, loc, [InMem mem])]
761 | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
762 expandNode vreg loc@(InMem src) (InBoth dst mem)
763 | src == mem = [(vreg, loc, [InReg dst])]
764 | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
765 expandNode vreg loc@(InBoth _ src) (InMem dst)
766 | src == dst = [] -- guaranteed to be true
767 expandNode vreg loc@(InBoth src _) (InReg dst)
769 expandNode vreg loc@(InBoth src _) dst
770 = expandNode vreg (InReg src) dst
771 expandNode vreg src dst
773 | otherwise = [(vreg, src, [dst])]
775 -- we have eliminated any possibility of single-node cylces
776 -- in expandNode above.
777 handleComponent (AcyclicSCC (vreg,src,dsts))
778 = return $ map (makeMove vreg src) dsts
780 -- we can not have cycles that involve memory
781 -- locations as source nor as single destination
782 -- because memory locations (stack slots) are
783 -- allocated exclusively for a virtual register and
784 -- therefore can not require a fixup
785 handleComponent (CyclicSCC ((vreg,src@(InReg sreg),dsts):rest))
787 spill_id <- getUniqueR
788 (saveInstr,slot) <- spillR (RealReg sreg) spill_id
789 remainingFixUps <- mapM handleComponent (stronglyConnCompR rest)
790 restoreAndFixInstr <- getRestoreMoves dsts slot
791 return ([instr] ++ concat remainingFixUps ++ restoreAndFixInstr)
793 getRestoreMoves [r@(InReg reg), mem@(InMem _)] slot
795 restoreToReg <- loadR (RealReg reg) slot
796 return $ [restoreToReg, makeMove vreg r mem]
797 getRestoreMoves [InReg reg] slot
798 = loadR (RealReg reg) slot >>= return . (:[])
799 getRestoreMoves [InMem _] _ = panic "getRestoreMoves can not handle memory only restores"
800 getRestoreMoves _ _ = panic "getRestoreMoves unknown case"
801 handleComponent (CyclicSCC _)
802 = panic "Register Allocator: handleComponent cyclic"
803 makeMove vreg (InReg src) (InReg dst)
804 = mkRegRegMoveInstr (RealReg src) (RealReg dst)
805 makeMove vreg (InMem src) (InReg dst)
806 = mkLoadInstr (RealReg dst) delta src
807 makeMove vreg (InReg src) (InMem dst)
808 = mkSpillInstr (RealReg src) delta dst
809 makeMove vreg src dst
810 = panic $ "makeMove " ++ show vreg ++ " (" ++ show src ++ ") ("
812 ++ " (workaround: use -fviaC)"
814 block_id <- getUniqueR
815 fixUpInstrs <- mapM handleComponent sccs
816 let block = BasicBlock (BlockId block_id) $
817 concat fixUpInstrs ++ mkBranchInstr dest
818 let instr' = patchJump instr dest (BlockId block_id)
819 joinToTargets block_live (block : new_blocks) instr' dests
821 live_set = lookItUp "joinToTargets" block_live dest
823 -- -----------------------------------------------------------------------------
824 -- The register allocator's monad.
826 -- Here we keep all the state that the register allocator keeps track
827 -- of as it walks the instructions in a basic block.
831 ra_blockassig :: BlockAssignment,
832 -- The current mapping from basic blocks to
833 -- the register assignments at the beginning of that block.
834 ra_freeregs :: {-#UNPACK#-}!FreeRegs, -- free machine registers
835 ra_assig :: RegMap Loc, -- assignment of temps to locations
836 ra_delta :: Int, -- current stack delta
837 ra_stack :: StackMap, -- free stack slots for spilling
838 ra_us :: UniqSupply -- unique supply for generating names
842 newtype RegM a = RegM { unReg :: RA_State -> (# RA_State, a #) }
844 instance Monad RegM where
845 m >>= k = RegM $ \s -> case unReg m s of { (# s, a #) -> unReg (k a) s }
846 return a = RegM $ \s -> (# s, a #)
848 runR :: BlockAssignment -> FreeRegs -> RegMap Loc -> StackMap -> UniqSupply
849 -> RegM a -> (BlockAssignment, StackMap, a)
850 runR block_assig freeregs assig stack us thing =
851 case unReg thing (RA_State{ ra_blockassig=block_assig, ra_freeregs=freeregs,
852 ra_assig=assig, ra_delta=0{-???-}, ra_stack=stack,
854 (# RA_State{ ra_blockassig=block_assig, ra_stack=stack' }, returned_thing #)
855 -> (block_assig, stack', returned_thing)
857 spillR :: Reg -> Unique -> RegM (Instr, Int)
858 spillR reg temp = RegM $ \ s@RA_State{ra_delta=delta, ra_stack=stack} ->
859 let (stack',slot) = getStackSlotFor stack temp
860 instr = mkSpillInstr reg delta slot
862 (# s{ra_stack=stack'}, (instr,slot) #)
864 loadR :: Reg -> Int -> RegM Instr
865 loadR reg slot = RegM $ \ s@RA_State{ra_delta=delta} ->
866 (# s, mkLoadInstr reg delta slot #)
868 getFreeRegsR :: RegM FreeRegs
869 getFreeRegsR = RegM $ \ s@RA_State{ra_freeregs = freeregs} ->
872 setFreeRegsR :: FreeRegs -> RegM ()
873 setFreeRegsR regs = RegM $ \ s ->
874 (# s{ra_freeregs = regs}, () #)
876 getAssigR :: RegM (RegMap Loc)
877 getAssigR = RegM $ \ s@RA_State{ra_assig = assig} ->
880 setAssigR :: RegMap Loc -> RegM ()
881 setAssigR assig = RegM $ \ s ->
882 (# s{ra_assig=assig}, () #)
884 getBlockAssigR :: RegM BlockAssignment
885 getBlockAssigR = RegM $ \ s@RA_State{ra_blockassig = assig} ->
888 setBlockAssigR :: BlockAssignment -> RegM ()
889 setBlockAssigR assig = RegM $ \ s ->
890 (# s{ra_blockassig = assig}, () #)
892 setDeltaR :: Int -> RegM ()
893 setDeltaR n = RegM $ \ s ->
894 (# s{ra_delta = n}, () #)
896 getDeltaR :: RegM Int
897 getDeltaR = RegM $ \s -> (# s, ra_delta s #)
899 getUniqueR :: RegM Unique
900 getUniqueR = RegM $ \s ->
901 case splitUniqSupply (ra_us s) of
902 (us1, us2) -> (# s{ra_us = us2}, uniqFromSupply us1 #)
904 -- -----------------------------------------------------------------------------
908 my_fromJust s p Nothing = pprPanic ("fromJust: " ++ s) p
909 my_fromJust s p (Just x) = x
911 my_fromJust _ _ = fromJust
914 lookItUp :: Uniquable b => String -> UniqFM a -> b -> a
915 lookItUp str fm x = my_fromJust str (ppr (getUnique x)) (lookupUFM fm x)