- handleComponent (CyclicSCC [one]) = []
- handleComponent (AcyclicSCC (src,_,[dst]))
- = makeMove src dst
- handleComponent (CyclicSCC things)
- = panic $ "Register Allocator: handleComponent: cyclic"
- ++ " (workaround: use -fviaC)"
-
- makeMove (InReg src) (InReg dst)
- = [mkRegRegMoveInstr (RealReg src) (RealReg dst)]
- makeMove (InMem src) (InReg dst)
- = [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)
-
- makeMove src dst
- = panic $ "makeMove (" ++ show src ++ ") ("
+ mkNodes src vreg =
+ expandNode vreg 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 vreg loc@(InReg src) (InBoth dst mem)
+ | src == dst = [(vreg, loc, [InMem mem])]
+ | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
+ expandNode vreg loc@(InMem src) (InBoth dst mem)
+ | src == mem = [(vreg, loc, [InReg dst])]
+ | otherwise = [(vreg, loc, [InReg dst, InMem mem])]
+ expandNode vreg loc@(InBoth _ src) (InMem dst)
+ | src == dst = [] -- guaranteed to be true
+ expandNode vreg loc@(InBoth src _) (InReg dst)
+ | src == dst = []
+ expandNode vreg loc@(InBoth src _) dst
+ = expandNode vreg (InReg src) dst
+ expandNode vreg src dst
+ | src == dst = []
+ | otherwise = [(vreg, src, [dst])]
+
+ -- we have eliminated any possibility of single-node cylces
+ -- in expandNode above.
+ handleComponent (AcyclicSCC (vreg,src,dsts))
+ = return $ map (makeMove vreg src) dsts
+
+ -- we can not have cycles that involve memory
+ -- locations as source nor as single destination
+ -- because memory locations (stack slots) are
+ -- allocated exclusively for a virtual register and
+ -- therefore can not require a fixup
+ handleComponent (CyclicSCC ((vreg,src@(InReg sreg),dsts):rest))
+ = do
+ spill_id <- getUniqueR
+ (saveInstr,slot) <- spillR (RealReg sreg) spill_id
+ remainingFixUps <- mapM handleComponent (stronglyConnCompR rest)
+ restoreAndFixInstr <- getRestoreMoves dsts slot
+ return ([instr] ++ concat remainingFixUps ++ restoreAndFixInstr)
+ where
+ getRestoreMoves [r@(InReg reg), mem@(InMem _)] slot
+ = do
+ restoreToReg <- loadR (RealReg reg) slot
+ return $ [restoreToReg, makeMove vreg r mem]
+ getRestoreMoves [InReg reg] slot
+ = loadR (RealReg reg) slot >>= return . (:[])
+ getRestoreMoves [InMem _] _ = panic "getRestoreMoves can not handle memory only restores"
+ getRestoreMoves _ _ = panic "getRestoreMoves unknown case"
+ handleComponent (CyclicSCC _)
+ = panic "Register Allocator: handleComponent cyclic"
+ makeMove vreg (InReg src) (InReg dst)
+ = mkRegRegMoveInstr (RealReg src) (RealReg dst)
+ makeMove vreg (InMem src) (InReg dst)
+ = mkLoadInstr (RealReg dst) delta src
+ makeMove vreg (InReg src) (InMem dst)
+ = mkSpillInstr (RealReg src) delta dst
+ makeMove vreg src dst
+ = panic $ "makeMove " ++ show vreg ++ " (" ++ show src ++ ") ("