1 -- | Register coalescing.
4 module RegAlloc.Graph.Coalesce (
11 import RegAlloc.Liveness
24 -- | Do register coalescing on this top level thing
25 -- For Reg -> Reg moves, if the first reg dies at the same time the second reg is born
26 -- then the mov only serves to join live ranges. The two regs can be renamed to be
27 -- the same and the move instruction safely erased.
31 -> UniqSM [LiveCmmTop instr]
35 let joins = foldl' unionBags emptyBag
36 $ map slurpJoinMovs code
38 let alloc = foldl' buildAlloc emptyUFM
41 let patched = map (patchEraseLive (sinkReg alloc)) code
46 buildAlloc :: UniqFM Reg -> (Reg, Reg) -> UniqFM Reg
47 buildAlloc fm (r1, r2)
48 = let rmin = min r1 r2
50 in addToUFM fm rmax rmin
52 sinkReg :: UniqFM Reg -> Reg -> Reg
54 = case lookupUFM fm r of
56 Just r' -> sinkReg fm r'
59 -- | Slurp out mov instructions that only serve to join live ranges.
60 -- During a mov, if the source reg dies and the destiation reg is born
61 -- then we can rename the two regs to the same thing and eliminate the move.
68 = slurpCmm emptyBag live
70 slurpCmm rs CmmData{} = rs
71 slurpCmm rs (CmmProc _ _ sccs) = foldl' slurpBlock rs (flattenSCCs sccs)
72 slurpBlock rs (BasicBlock _ instrs) = foldl' slurpLI rs instrs
74 slurpLI rs (LiveInstr _ Nothing) = rs
75 slurpLI rs (LiveInstr instr (Just live))
76 | Just (r1, r2) <- takeRegRegMoveInstr instr
77 , elementOfUniqSet r1 $ liveDieRead live
78 , elementOfUniqSet r2 $ liveBorn live
80 -- only coalesce movs between two virtuals for now, else we end up with
81 -- allocatable regs in the live regs list..
82 , isVirtualReg r1 && isVirtualReg r2