+ do
+ delta <- getDeltaR
+ -- Construct a graph of register/spill movements and
+ -- untangle it component by component.
+ --
+ -- We cut some corners by
+ -- a) not handling cyclic components
+ -- b) not handling memory-to-memory moves.
+ --
+ -- Cyclic components seem to occur only very rarely,
+ -- and we don't need memory-to-memory moves because we
+ -- 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 ]
+ sccs = stronglyConnCompR graph
+
+ 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 ++ ") ("
+ ++ show dst ++ ")"
+ ++ " (workaround: use -fviaC)"
+
+ block_id <- getUniqueR
+ let block = BasicBlock (BlockId block_id) $
+ concatMap handleComponent sccs ++ mkBranchInstr dest
+ let instr' = patchJump instr dest (BlockId block_id)
+ joinToTargets block_live (block : new_blocks) instr' dests