-- register does not already have an assignment, then we can
-- eliminate the instruction.
case isRegRegMove instr of
- Just (src,dst)
- | src `elem` r_dying,
- isVirtualReg dst,
- Just loc <- lookupUFM assig src,
- not (dst `elemUFM` assig) -> do
- setAssigR (addToUFM (delFromUFM assig src) dst loc)
- return (new_instrs, [])
+ Just (src,dst) | src `elem` r_dying,
+ isVirtualReg dst,
+ not (dst `elemUFM` assig) -> do
+ case src of
+ RealReg i -> setAssigR (addToUFM assig dst (InReg i))
+ -- if src is a fixed reg, then we just map dest to this
+ -- reg in the assignment. src must be an allocatable reg,
+ -- otherwise it wouldn't be in r_dying.
+ _virt -> case lookupUFM assig src of
+ Nothing -> panic "raInsn"
+ Just loc ->
+ setAssigR (addToUFM (delFromUFM assig src) dst loc)
+
+ -- we have elimianted this instruction
+ {-
+ freeregs <- getFreeRegsR
+ assig <- getAssigR
+ pprTrace "raInsn" (text "ELIMINATED: " <> docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ text (show freeregs) $$ ppr assig) $ do
+ -}
+ return (new_instrs, [])
other -> genRaInsn block_live new_instrs instr r_dying w_dying
-- make sure that every temporary always gets its own
-- stack slot.
- let graph = [ (loc0, loc0,
- [lookupWithDefaultUFM_Directly
- dest_assig
- (panic "RegisterAlloc.joinToTargets")
- vreg]
- )
- | (vreg, loc0) <- ufmToList adjusted_assig ]
+ let graph = [ node | (vreg, src) <- ufmToList adjusted_assig,
+ node <- mkNodes src vreg ]
+
sccs = stronglyConnCompR graph
- handleComponent (CyclicSCC [one]) = []
- handleComponent (AcyclicSCC (src,_,[dst]))
- = makeMove src dst
+ mkNodes src vreg =
+ expandNode src (lookupWithDefaultUFM_Directly
+ dest_assig
+ (panic "RegisterAlloc.joinToTargets")
+ vreg)
+
+ -- The InBoth handling is a little tricky here. If
+ -- the destination is InBoth, then we must ensure that
+ -- the value ends up in both locations. An InBoth
+ -- destination must conflict with an InReg or InMem
+ -- source, so we expand an InBoth destination as
+ -- necessary. An InBoth source is slightly different:
+ -- we only care about the register that the source value
+ -- is in, so that we can move it to the destinations.
+
+ expandNode loc@(InReg src) (InBoth dst mem)
+ | src == dst = [(loc, loc, [InMem dst])]
+ | otherwise = [(loc, loc, [InReg dst, InMem mem])]
+ expandNode loc@(InMem src) (InBoth dst mem)
+ | src == mem = [(loc, loc, [InReg dst])]
+ | otherwise = [(loc, loc, [InReg dst, InMem mem])]
+ expandNode loc@(InBoth _ src) (InMem dst)
+ | src == dst = [] -- guaranteed to be true
+ expandNode loc@(InBoth src _) (InReg dst)
+ | src == dst = []
+ expandNode loc@(InBoth src _) dst
+ = expandNode (InReg src) dst
+ expandNode src dst
+ | src == dst = []
+ | otherwise = [(src, src, [dst])]
+
+ -- we have eliminated any possibility of single-node cylces
+ -- in expandNode above.
+ handleComponent (AcyclicSCC (src,_,dsts))
+ = map (makeMove src) dsts
handleComponent (CyclicSCC things)
= panic $ "Register Allocator: handleComponent: cyclic"
++ " (workaround: use -fviaC)"
makeMove (InReg src) (InReg dst)
- = [mkRegRegMoveInstr (RealReg src) (RealReg dst)]
+ = mkRegRegMoveInstr (RealReg src) (RealReg dst)
makeMove (InMem src) (InReg dst)
- = [mkLoadInstr (RealReg dst) delta src]
+ = mkLoadInstr (RealReg dst) delta src
makeMove (InReg src) (InMem dst)
- = [mkSpillInstr (RealReg src) delta dst]
-
- makeMove (InBoth src _) (InReg dst)
- | src == dst = []
- makeMove (InBoth _ src) (InMem dst)
- | src == dst = []
- makeMove (InBoth src _) dst
- = makeMove (InReg src) dst
- makeMove (InReg src) (InBoth dstR dstM)
- | src == dstR
- = makeMove (InReg src) (InMem dstM)
- | otherwise
- = makeMove (InReg src) (InReg dstR)
- ++ makeMove (InReg src) (InMem dstM)
-
+ = mkSpillInstr (RealReg src) delta dst
makeMove src dst
= panic $ "makeMove (" ++ show src ++ ") ("
++ show dst ++ ")"