Small improvement to GraphColor.selectColor
[ghc-hetmet.git] / compiler / nativeGen / RegAllocColor.hs
index 45727c5..8449b5e 100644 (file)
@@ -12,6 +12,7 @@
 --
 --     Colors in graphviz graphs could be nicer.
 --
+{-# OPTIONS -fno-warn-missing-signatures #-}
 
 module RegAllocColor ( 
        regAlloc,
@@ -23,10 +24,10 @@ where
 import qualified GraphColor    as Color
 import RegLiveness
 import RegSpill
+import RegSpillClean
 import RegAllocStats
 import MachRegs
 import MachInstrs
-import RegCoalesce
 import PprMach
 
 import UniqSupply
@@ -34,6 +35,7 @@ import UniqSet
 import UniqFM
 import Bag
 import Outputable
+import Util
 
 import Data.List
 import Data.Maybe
@@ -60,7 +62,7 @@ regAlloc
                
 regAlloc dump regsFree slotsFree code
  = do
-       (code_final, debug_codeGraphs, graph_final)
+       (code_final, debug_codeGraphs, _)
                <- regAlloc_spin dump 0 trivColorable regsFree slotsFree [] code
        
        return  ( code_final
@@ -78,11 +80,12 @@ regAlloc_spin dump (spinCount :: Int) triv regsFree slotsFree debug_codeGraphs c
                $$ text "slotsFree   = " <> ppr (sizeUniqSet slotsFree))
 
        -- build a conflict graph from the code.
-       graph           <- buildGraph code
+       graph           <- {-# SCC "BuildGraph" #-} buildGraph code
 
        -- build a map of how many instructions each reg lives for.
        --      this is lazy, it won't be computed unless we need to spill
-       let fmLife      = plusUFMs_C (\(r1, l1) (r2, l2) -> (r1, l1 + l2))
+
+       let fmLife      = {-# SCC "LifetimeCount" #-} plusUFMs_C (\(r1, l1) (_, l2) -> (r1, l1 + l2))
                        $ map lifetimeCount code
 
        -- record startup state
@@ -99,19 +102,30 @@ regAlloc_spin dump (spinCount :: Int) triv regsFree slotsFree debug_codeGraphs c
        let spill       = chooseSpill_maxLife fmLife
        
        -- try and color the graph 
-       let (graph_colored, rsSpill)    
-                       = Color.colorGraph regsFree triv spill graph
+       let (graph_colored, rsSpill, rmCoalesce)
+                       = {-# SCC "ColorGraph" #-} Color.colorGraph regsFree triv spill graph
+
+       -- rewrite regs in the code that have been coalesced
+       let patchF reg  = case lookupUFM rmCoalesce reg of
+                               Just reg'       -> reg'
+                               Nothing         -> reg
+       let code_coalesced
+                       = map (patchEraseLive patchF) code
+
 
        -- see if we've found a coloring
        if isEmptyUniqSet rsSpill
         then do
                -- patch the registers using the info in the graph
-               let code_patched        = map (patchRegsFromGraph graph_colored) code
+               let code_patched        = map (patchRegsFromGraph graph_colored) code_coalesced
+
+               -- clean out unneeded SPILL/RELOADs
+               let code_spillclean     = map cleanSpills code_patched
 
                -- strip off liveness information
                let code_nat            = map stripLive code_patched
 
-               -- rewrite SPILL/REALOAD pseudos into real instructions
+               -- rewrite SPILL/RELOAD pseudos into real instructions
                let spillNatTop         = mapGenBlockTop spillNatBlock
                let code_final          = map spillNatTop code_nat
                
@@ -119,20 +133,29 @@ regAlloc_spin dump (spinCount :: Int) triv regsFree slotsFree debug_codeGraphs c
                let stat                =
                        RegAllocStatsColored
                        { raGraph       = graph_colored
-                       , raPatchedCmm  = code_patched
-                       , raFinalCmm    = code_final }
+                       , raCoalesced   = rmCoalesce
+                       , raPatched     = code_patched
+                       , raSpillClean  = code_spillclean
+                       , raFinal       = code_final
+                       , raSRMs        = foldl addSRM (0, 0, 0) $ map countSRMs code_spillclean }
 
-               return  ( code_nat
-                       , if dump
-                               then [stat] ++ maybeToList stat1 ++ debug_codeGraphs
+
+               let statList =
+                       if dump then [stat] ++ maybeToList stat1 ++ debug_codeGraphs
                                else []
+
+               -- space leak avoidance
+               seqList statList $! return ()
+
+               return  ( code_final
+                       , statList
                        , graph_colored)
 
         else do
                -- spill the uncolored regs
                (code_spilled, slotsFree', spillStats)
-                       <- regSpill code slotsFree rsSpill
-                       
+                       <- regSpill code_coalesced slotsFree rsSpill
+
                -- recalculate liveness
                let code_nat    = map stripLive code_spilled
                code_relive     <- mapM regLiveness code_nat
@@ -141,15 +164,21 @@ regAlloc_spin dump (spinCount :: Int) triv regsFree slotsFree debug_codeGraphs c
                let stat        =
                        RegAllocStatsSpill
                        { raGraph       = graph_colored
+                       , raCoalesced   = rmCoalesce
                        , raSpillStats  = spillStats
                        , raLifetimes   = fmLife
                        , raSpilled     = code_spilled }
                                
-               -- try again
-               regAlloc_spin dump (spinCount + 1) triv regsFree slotsFree'
-                       (if dump
+               let statList =
+                       if dump
                                then [stat] ++ maybeToList stat1 ++ debug_codeGraphs
-                               else [])
+                               else []
+
+               -- space leak avoidance
+               seqList statList $! return ()
+
+               regAlloc_spin dump (spinCount + 1) triv regsFree slotsFree'
+                       statList
                        code_relive
 
  
@@ -201,16 +230,20 @@ buildGraph
        
 buildGraph code
  = do
-       -- Add the reg-reg conflicts to the graph
-       let conflictSets        = unionManyBags (map slurpConflicts code)
-       let graph_conflict      = foldrBag graphAddConflictSet Color.initGraph conflictSets
+       -- Slurp out the conflicts and reg->reg moves from this code
+       let (conflictList, moveList) =
+               unzip $ map slurpConflicts code
+
+       let conflictBag         = unionManyBags conflictList
+       let moveBag             = unionManyBags moveList
 
+       -- Add the reg-reg conflicts to the graph
+       let graph_conflict      = foldrBag graphAddConflictSet Color.initGraph conflictBag
 
        -- Add the coalescences edges to the graph.
-       let coalesce            = unionManyBags (map slurpJoinMovs code)
-       let graph_coalesce      = foldrBag graphAddCoalesce graph_conflict coalesce
+       let graph_coalesce      = foldrBag graphAddCoalesce graph_conflict moveBag
                        
-       return  $ graph_coalesce
+       return  graph_coalesce
 
 
 -- | Add some conflict edges to the graph.
@@ -244,10 +277,10 @@ graphAddCoalesce
        -> Color.Graph Reg RegClass Reg
        
 graphAddCoalesce (r1, r2) graph
-       | RealReg regno <- r1
+       | RealReg _ <- r1
        = Color.addPreference (regWithClass r2) r1 graph
        
-       | RealReg regno <- r2
+       | RealReg _ <- r2
        = Color.addPreference (regWithClass r1) r2 graph
        
        | otherwise
@@ -280,7 +313,7 @@ patchRegsFromGraph graph code
                = pprPanic "patchRegsFromGraph: register mapping failed." 
                        (  text "There is no node in the graph for register " <> ppr reg
                        $$ ppr code
-                       $$ Color.dotGraph (\x -> text "white") trivColorable graph)
+                       $$ Color.dotGraph (\_ -> text "white") trivColorable graph)
        
    in  patchEraseLive patchF code
    
@@ -289,3 +322,4 @@ plusUFMs_C  :: (elt -> elt -> elt) -> [UniqFM elt] -> UniqFM elt
 plusUFMs_C f maps
        = foldl (plusUFM_C f) emptyUFM maps
        
+