module RegAlloc.Graph.Coalesce (
        regCoalesce,
        slurpJoinMovs
) where
import GhcPrelude
import RegAlloc.Liveness
import Instruction
import Reg
import Cmm
import Bag
import Digraph
import UniqFM
import UniqSet
import UniqSupply
import Data.List
regCoalesce
        :: Instruction instr
        => [LiveCmmDecl statics instr]
        -> UniqSM [LiveCmmDecl statics instr]
regCoalesce code
 = do
        let joins       = foldl' unionBags emptyBag
                        $ map slurpJoinMovs code
        let alloc       = foldl' buildAlloc emptyUFM
                        $ bagToList joins
        let patched     = map (patchEraseLive (sinkReg alloc)) code
        return patched
buildAlloc :: UniqFM Reg -> (Reg, Reg) -> UniqFM Reg
buildAlloc fm (r1, r2)
 = let  rmin    = min r1 r2
        rmax    = max r1 r2
   in   addToUFM fm rmax rmin
sinkReg :: UniqFM Reg -> Reg -> Reg
sinkReg fm r
 = case lookupUFM fm r of
        Nothing -> r
        Just r' -> sinkReg fm r'
slurpJoinMovs
        :: Instruction instr
        => LiveCmmDecl statics instr
        -> Bag (Reg, Reg)
slurpJoinMovs live
        = slurpCmm emptyBag live
 where
        slurpCmm   rs  CmmData{}
         = rs
        slurpCmm   rs (CmmProc _ _ _ sccs)
         = foldl' slurpBlock rs (flattenSCCs sccs)
        slurpBlock rs (BasicBlock _ instrs)
         = foldl' slurpLI    rs instrs
        slurpLI    rs (LiveInstr _      Nothing)    = rs
        slurpLI    rs (LiveInstr instr (Just live))
                | Just (r1, r2) <- takeRegRegMoveInstr instr
                , elementOfUniqSet r1 $ liveDieRead live
                , elementOfUniqSet r2 $ liveBorn live
                
                
                
                , isVirtualReg r1 && isVirtualReg r2
                = consBag (r1, r2) rs
                | otherwise
                = rs