Add {-# OPTIONS_GHC -w #-} and some blurb to all compiler modules
[ghc-hetmet.git] / compiler / nativeGen / RegAllocStats.hs
index ae5f106..aad51c7 100644 (file)
@@ -2,14 +2,24 @@
 -- Carries interesting info for debugging / profiling of the 
 --     graph coloring register allocator.
 
+{-# OPTIONS_GHC -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+--     http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions#Warnings
+-- for details
+
 module RegAllocStats (
        RegAllocStats (..),
        regDotColor,
 
+       pprStats,
        pprStatsSpills,
        pprStatsLifetimes,
        pprStatsConflict,
-       pprStatsLifeConflict
+       pprStatsLifeConflict,
+
+       countSRMs, addSRM
 )
 
 where
@@ -18,60 +28,92 @@ where
 
 import qualified GraphColor as Color
 import RegLiveness
+import RegAllocInfo
 import RegSpill
 import MachRegs
+import MachInstrs
+import Cmm
 
 import Outputable
 import UniqFM
 import UniqSet
+import State
 
 import Data.List
 
 data RegAllocStats
 
+       -- initial graph
+       = RegAllocStatsStart
+       { raLiveCmm     :: [LiveCmmTop]                   -- ^ initial code, with liveness
+       , raGraph       :: Color.Graph Reg RegClass Reg  -- ^ the initial, uncolored graph
+       , raLifetimes   :: UniqFM (Reg, Int) }            -- ^ number of instrs each reg lives for
+
        -- a spill stage
-       = RegAllocStatsSpill
-       { raLiveCmm     :: [LiveCmmTop]                 -- ^ code we tried to allocate regs for
-       , raGraph       :: Color.Graph Reg RegClass Reg -- ^ the partially colored graph
+       | RegAllocStatsSpill
+       { raGraph       :: Color.Graph Reg RegClass Reg -- ^ the partially colored graph
        , raSpillStats  :: SpillStats                   -- ^ spiller stats
-       , raLifetimes   :: UniqFM (Reg, Int) }          -- ^ number of instrs each reg lives for
+       , raLifetimes   :: UniqFM (Reg, Int)            -- ^ number of instrs each reg lives for
+       , raSpilled     :: [LiveCmmTop] }               -- ^ code with spill instructions added
 
        -- a successful coloring
        | RegAllocStatsColored
-       { raLiveCmm     :: [LiveCmmTop]                 -- ^ the code we allocated regs for
-       , raGraph       :: Color.Graph Reg RegClass Reg -- ^ the colored graph
-       , raPatchedCmm  :: [LiveCmmTop]                 -- ^ code with register allocation
-       , raLifetimes   :: UniqFM (Reg, Int) }          -- ^ number of instrs each reg lives for
-
+       { raGraph       :: Color.Graph Reg RegClass Reg -- ^ the colored graph
+       , raPatched     :: [LiveCmmTop]                 -- ^ code with vregs replaced by hregs
+       , raSpillClean  :: [LiveCmmTop]                 -- ^ code with unneeded spill/reloads cleaned out
+       , raFinal       :: [NatCmmTop]                  -- ^ final code
+       , raSRMs        :: (Int, Int, Int) }            -- ^ spill/reload/reg-reg moves present in this code
 
 instance Outputable RegAllocStats where
 
- ppr (s@RegAllocStatsSpill{})
-       = text "-- Spill"
-
-       $$ text "-- Native code with liveness information."
+ ppr (s@RegAllocStatsStart{})
+       =  text "#  Start"
+       $$ text "#  Native code with liveness information."
        $$ ppr (raLiveCmm s)
-       $$ text " "
-
-       $$ text "-- Register conflict graph."
+       $$ text ""
+       $$ text "#  Initial register conflict graph."
        $$ Color.dotGraph regDotColor trivColorable (raGraph s)
 
-       $$ text "-- Spill statistics."
+ ppr (s@RegAllocStatsSpill{})
+       =  text "#  Spill"
+       $$ text "#  Register conflict graph."
+       $$ Color.dotGraph regDotColor trivColorable (raGraph s)
+       $$ text ""
+       $$ text "#  Spills inserted."
        $$ ppr (raSpillStats s)
+       $$ text ""
+       $$ text "#  Code with spills inserted."
+       $$ (ppr (raSpilled s))
 
-
- ppr (s@RegAllocStatsColored{})
-       = text "-- Colored"
-
-       $$ text "-- Native code with liveness information."
-       $$ ppr (raLiveCmm s)
-       $$ text " "
-
-       $$ text "-- Register conflict graph."
+ ppr (s@RegAllocStatsColored { raSRMs = (spills, reloads, moves) })
+       =  text "#  Colored"
+       $$ text "#  Register conflict graph."
        $$ Color.dotGraph regDotColor trivColorable (raGraph s)
-
-       $$ text "-- Native code after register allocation."
-       $$ ppr (raPatchedCmm s)
+       $$ text ""
+       $$ text "#  Native code after register allocation."
+       $$ ppr (raPatched s)
+       $$ text ""
+       $$ text "#  Clean out unneeded spill/reloads."
+       $$ ppr (raSpillClean s)
+       $$ text ""
+       $$ text "#  Final code, after rewriting spill/rewrite pseudo instrs."
+       $$ ppr (raFinal s)
+       $$ text ""
+       $$  text "#  Score:"
+       $$ (text "#          spills  inserted: " <> int spills)
+       $$ (text "#          reloads inserted: " <> int reloads)
+       $$ (text "#   reg-reg moves remaining: " <> int moves)
+       $$ text ""
+
+-- | Do all the different analysis on this list of RegAllocStats
+pprStats :: [RegAllocStats] -> Color.Graph Reg RegClass Reg -> SDoc
+pprStats stats graph
+ = let         outSpills       = pprStatsSpills    stats
+       outLife         = pprStatsLifetimes stats
+       outConflict     = pprStatsConflict  stats
+       outScatter      = pprStatsLifeConflict stats graph
+
+  in   vcat [outSpills, outLife, outConflict, outScatter]
 
 
 -- | Dump a table of how many spill loads / stores were inserted for each vreg.
@@ -79,31 +121,26 @@ pprStatsSpills
        :: [RegAllocStats] -> SDoc
 
 pprStatsSpills stats
- = let -- slurp out the stats from all the spiller stages
-       spillStats      = [ s   | s@RegAllocStatsSpill{} <- stats]
-
-       -- build a map of how many spill load/stores were inserted for each vreg
-       spillLS         = foldl' (plusUFM_C accSpillLS) emptyUFM
-                       $ map (spillLoadStore . raSpillStats) spillStats
+ = let
+       finals  = [ s   | s@RegAllocStatsColored{} <- stats]
 
-       -- print the count of load/spills as a tuple so we can read back from the file easilly
-       pprSpillLS (r, loads, stores)
-        = (parens $ (hcat $ punctuate (text ", ") [doubleQuotes (ppr r), int loads, int stores]))
+       -- sum up how many stores/loads/reg-reg-moves were left in the code
+       total   = foldl' addSRM (0, 0, 0)
+               $ map raSRMs finals
 
-
-    in (  text "-- spills-added"
-       $$ text "--    (reg_name, spill_loads_added, spill_stores_added)."
-       $$ (vcat $ map pprSpillLS $ eltsUFM spillLS)
-       $$ text "\n")
+    in (  text "-- spills-added-total"
+       $$ text "--    (stores, loads, reg_reg_moves_remaining)"
+       $$ ppr total
+       $$ text "")
 
 
-
--- | Dump a table of how long vregs tend to live for.
+-- | Dump a table of how long vregs tend to live for in the initial code.
 pprStatsLifetimes
        :: [RegAllocStats] -> SDoc
 
 pprStatsLifetimes stats
- = let lifeMap         = foldl' plusUFM emptyUFM $ map raLifetimes stats
+ = let lifeMap         = foldl' plusUFM emptyUFM
+                               [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
        lifeBins        = binLifetimeCount lifeMap
 
    in  (  text "-- vreg-population-lifetimes"
@@ -123,7 +160,7 @@ binLifetimeCount fm
                lifes
 
 
--- | Dump a table of how many conflicts vregs tend to have.
+-- | Dump a table of how many conflicts vregs tend to have in the initial code.
 pprStatsConflict
        :: [RegAllocStats] -> SDoc
 
@@ -131,7 +168,7 @@ pprStatsConflict stats
  = let confMap = foldl' (plusUFM_C (\(c1, n1) (c2, n2) -> (c1, n1 + n2)))
                        emptyUFM
                $ map Color.slurpNodeConflictCount
-               $ map raGraph stats
+                       [ raGraph s | s@RegAllocStatsStart{} <- stats ]
 
    in  (  text "-- vreg-conflicts"
        $$ text "--   (conflict_count, number_of_vregs_that_had_that_many_conflicts)"
@@ -142,12 +179,18 @@ pprStatsConflict stats
 -- | For every vreg, dump it's how many conflicts it has and its lifetime
 --     good for making a scatter plot.
 pprStatsLifeConflict
-       :: [RegAllocStats] -> Color.Graph Reg RegClass Reg -> SDoc
+       :: [RegAllocStats]
+       -> Color.Graph Reg RegClass Reg         -- ^ global register conflict graph
+       -> SDoc
 
 pprStatsLifeConflict stats graph
- = let lifeMap = foldl' plusUFM emptyUFM $ map raLifetimes stats
-       scatter = map   (\r ->  let Just (_, lifetime)  = lookupUFM lifeMap r
-                                   Just node           = Color.lookupNode graph r
+ = let lifeMap = foldl' plusUFM emptyUFM
+                       [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
+
+       scatter = map   (\r ->  let lifetime    = case lookupUFM lifeMap r of
+                                                       Just (_, l)     -> l
+                                                       Nothing         -> 0
+                                   Just node   = Color.lookupNode graph r
                                in parens $ hcat $ punctuate (text ", ")
                                        [ doubleQuotes $ ppr $ Color.nodeId node
                                        , ppr $ sizeUniqSet (Color.nodeConflicts node)
@@ -162,6 +205,37 @@ pprStatsLifeConflict stats graph
        $$ text "\n")
 
 
+-- | Count spill/reload/reg-reg moves.
+--     Lets us see how well the register allocator has done.
+--
+countSRMs :: LiveCmmTop -> (Int, Int, Int)
+countSRMs cmm
+       = execState (mapBlockTopM countSRM_block cmm) (0, 0, 0)
+
+countSRM_block (BasicBlock i instrs)
+ = do  instrs' <- mapM countSRM_instr instrs
+       return  $ BasicBlock i instrs'
+
+countSRM_instr li@(Instr instr live)
+       | SPILL reg slot        <- instr
+       = do    modify  $ \(s, r, m)    -> (s + 1, r, m)
+               return li
+
+       | RELOAD slot reg       <- instr
+       = do    modify  $ \(s, r, m)    -> (s, r + 1, m)
+               return li
+
+       | Just _                <- isRegRegMove instr
+       = do    modify  $ \(s, r, m)    -> (s, r, m + 1)
+               return li
+
+       | otherwise
+       =       return li
+
+-- sigh..
+addSRM (s1, r1, m1) (s2, r2, m2)
+       = (s1+s2, r1+r2, m1+m2)
+
 -----
 -- Register colors for drawing conflict graphs
 --     Keep this out of MachRegs.hs because it's specific to the graph coloring allocator.