2 -- Carries interesting info for debugging / profiling of the
3 -- graph coloring register allocator.
18 #include "nativeGen/NCG.h"
20 import qualified GraphColor as Color
36 { raLiveCmm :: [LiveCmmTop] -- ^ initial code, with liveness
37 , raGraph :: Color.Graph Reg RegClass Reg -- ^ the initial, uncolored graph
38 , raLifetimes :: UniqFM (Reg, Int) } -- ^ number of instrs each reg lives for
42 { raGraph :: Color.Graph Reg RegClass Reg -- ^ the partially colored graph
43 , raSpillStats :: SpillStats -- ^ spiller stats
44 , raLifetimes :: UniqFM (Reg, Int) -- ^ number of instrs each reg lives for
45 , raSpilled :: [LiveCmmTop] } -- ^ code with spill instructions added
47 -- a successful coloring
48 | RegAllocStatsColored
49 { raGraph :: Color.Graph Reg RegClass Reg -- ^ the colored graph
50 , raPatched :: [LiveCmmTop] -- ^ code with vregs replaced by hregs
51 , raSpillClean :: [LiveCmmTop] -- ^ code with unneeded spill/reloads cleaned out
52 , raFinal :: [NatCmmTop] } -- ^ final code
54 instance Outputable RegAllocStats where
56 ppr (s@RegAllocStatsStart{})
58 $$ text "# Native code with liveness information."
61 $$ text "# Initial register conflict graph."
62 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
64 ppr (s@RegAllocStatsSpill{})
66 $$ text "# Register conflict graph."
67 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
69 $$ text "# Spills inserted."
70 $$ ppr (raSpillStats s)
72 $$ text "# Code with spills inserted."
73 $$ (ppr (raSpilled s))
75 ppr (s@RegAllocStatsColored{})
77 $$ text "# Register conflict graph."
78 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
80 $$ text "# Native code after register allocation."
83 $$ text "# Clean out unneeded spill/reloads."
84 $$ ppr (raSpillClean s)
86 $$ text "# Final code, after rewriting spill/rewrite pseudo instrs."
91 -- | Do all the different analysis on this list of RegAllocStats
92 pprStats :: [RegAllocStats] -> Color.Graph Reg RegClass Reg -> SDoc
94 = let outSpills = pprStatsSpills stats
95 outLife = pprStatsLifetimes stats
96 outConflict = pprStatsConflict stats
97 outScatter = pprStatsLifeConflict stats graph
99 in vcat [outSpills, outLife, outConflict, outScatter]
102 -- | Dump a table of how many spill loads / stores were inserted for each vreg.
104 :: [RegAllocStats] -> SDoc
107 = let -- slurp out the stats from all the spiller stages
108 spillStats = [ s | s@RegAllocStatsSpill{} <- stats]
110 -- build a map of how many spill load/stores were inserted for each vreg
111 spillSL = foldl' (plusUFM_C accSpillSL) emptyUFM
112 $ map (spillStoreLoad . raSpillStats) spillStats
114 -- print the count of load/spills as a tuple so we can read back from the file easilly
115 pprSpillSL (r, loads, stores)
116 = (parens $ (hcat $ punctuate (text ", ") [doubleQuotes (ppr r), int loads, int stores]))
118 -- sum up the total number of spill instructions inserted
119 spillList = eltsUFM spillSL
120 spillTotal = foldl' (\(s1, l1) (s2, l2) -> (s1 + s2, l1 + l2))
122 $ map (\(n, s, l) -> (s, l))
125 in ( text "-- spills-added-total"
126 $$ text "-- (stores, loads)"
129 $$ text "-- spills-added"
130 $$ text "-- (reg_name, stores, loads)"
131 $$ (vcat $ map pprSpillSL $ spillList)
135 -- | Dump a table of how long vregs tend to live for in the initial code.
137 :: [RegAllocStats] -> SDoc
139 pprStatsLifetimes stats
140 = let lifeMap = foldl' plusUFM emptyUFM
141 [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
142 lifeBins = binLifetimeCount lifeMap
144 in ( text "-- vreg-population-lifetimes"
145 $$ text "-- (instruction_count, number_of_vregs_that_lived_that_long)"
146 $$ (vcat $ map ppr $ eltsUFM lifeBins)
149 binLifetimeCount :: UniqFM (Reg, Int) -> UniqFM (Int, Int)
151 = let lifes = map (\l -> (l, (l, 1)))
156 (\(l1, c1) (l2, c2) -> (l1, c1 + c2))
161 -- | Dump a table of how many conflicts vregs tend to have in the initial code.
163 :: [RegAllocStats] -> SDoc
165 pprStatsConflict stats
166 = let confMap = foldl' (plusUFM_C (\(c1, n1) (c2, n2) -> (c1, n1 + n2)))
168 $ map Color.slurpNodeConflictCount
169 [ raGraph s | s@RegAllocStatsStart{} <- stats ]
171 in ( text "-- vreg-conflicts"
172 $$ text "-- (conflict_count, number_of_vregs_that_had_that_many_conflicts)"
173 $$ (vcat $ map ppr $ eltsUFM confMap)
177 -- | For every vreg, dump it's how many conflicts it has and its lifetime
178 -- good for making a scatter plot.
181 -> Color.Graph Reg RegClass Reg -- ^ global register conflict graph
184 pprStatsLifeConflict stats graph
185 = let lifeMap = foldl' plusUFM emptyUFM
186 [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
188 scatter = map (\r -> let lifetime = case lookupUFM lifeMap r of
191 Just node = Color.lookupNode graph r
192 in parens $ hcat $ punctuate (text ", ")
193 [ doubleQuotes $ ppr $ Color.nodeId node
194 , ppr $ sizeUniqSet (Color.nodeConflicts node)
198 $ Color.graphMap graph
200 in ( text "-- vreg-conflict-lifetime"
201 $$ text "-- (vreg, vreg_conflicts, vreg_lifetime)"
207 -- Register colors for drawing conflict graphs
208 -- Keep this out of MachRegs.hs because it's specific to the graph coloring allocator.
211 -- reg colors for x86
213 regDotColor :: Reg -> SDoc
215 = let Just str = lookupUFM regColors reg
230 , (fake5, "#5500ff") ]
234 -- reg colors for x86_64
235 #if x86_64_TARGET_ARCH
236 regDotColor :: Reg -> SDoc
238 = let Just str = lookupUFM regColors reg
243 $ [ (rax, "#00ff00"), (eax, "#00ff00")
244 , (rbx, "#0000ff"), (ebx, "#0000ff")
245 , (rcx, "#00ffff"), (ecx, "#00ffff")
246 , (rdx, "#0080ff"), (edx, "#00ffff")
256 ++ zip (map RealReg [16..31]) (repeat "red")
260 -- reg colors for ppc
261 #if powerpc_TARGET_ARCH
262 regDotColor :: Reg -> SDoc
264 = case regClass reg of
265 RcInteger -> text "blue"
266 RcFloat -> text "red"
272 = let rs = padL 2 '0' (showHex r "")
273 gs = padL 2 '0' (showHex r "")
274 bs = padL 2 '0' (showHex r "")
277 = replicate (n - length s) c ++ s
278 in "#" ++ rs ++ gs ++ bs