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 , raPatchedCmm :: [LiveCmmTop] -- ^ code after register allocation
51 , raFinalCmm :: [NatCmmTop] } -- ^ final code
53 instance Outputable RegAllocStats where
55 ppr (s@RegAllocStatsStart{})
57 $$ text "# Native code with liveness information."
60 $$ text "# Initial register conflict graph."
61 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
63 ppr (s@RegAllocStatsSpill{})
65 $$ text "# Register conflict graph."
66 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
68 $$ text "# Spills inserted."
69 $$ ppr (raSpillStats s)
71 $$ text "# Code with spills inserted."
72 $$ (ppr (raSpilled s))
74 ppr (s@RegAllocStatsColored{})
76 $$ text "# Register conflict graph."
77 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
79 $$ text "# Native code after register allocation."
80 $$ ppr (raPatchedCmm s)
82 $$ text "# Final code, after rewriting spill/rewrite pseudo instrs."
87 -- | Do all the different analysis on this list of RegAllocStats
88 pprStats :: [RegAllocStats] -> Color.Graph Reg RegClass Reg -> SDoc
90 = let outSpills = pprStatsSpills stats
91 outLife = pprStatsLifetimes stats
92 outConflict = pprStatsConflict stats
93 outScatter = pprStatsLifeConflict stats graph
95 in vcat [outSpills, outLife, outConflict, outScatter]
98 -- | Dump a table of how many spill loads / stores were inserted for each vreg.
100 :: [RegAllocStats] -> SDoc
103 = let -- slurp out the stats from all the spiller stages
104 spillStats = [ s | s@RegAllocStatsSpill{} <- stats]
106 -- build a map of how many spill load/stores were inserted for each vreg
107 spillSL = foldl' (plusUFM_C accSpillSL) emptyUFM
108 $ map (spillStoreLoad . raSpillStats) spillStats
110 -- print the count of load/spills as a tuple so we can read back from the file easilly
111 pprSpillSL (r, loads, stores)
112 = (parens $ (hcat $ punctuate (text ", ") [doubleQuotes (ppr r), int loads, int stores]))
114 -- sum up the total number of spill instructions inserted
115 spillList = eltsUFM spillSL
116 spillTotal = foldl' (\(s1, l1) (s2, l2) -> (s1 + s2, l1 + l2))
118 $ map (\(n, s, l) -> (s, l))
121 in ( text "-- spills-added-total"
122 $$ text "-- (stores, loads)"
125 $$ text "-- spills-added"
126 $$ text "-- (reg_name, stores, loads)"
127 $$ (vcat $ map pprSpillSL $ spillList)
131 -- | Dump a table of how long vregs tend to live for in the initial code.
133 :: [RegAllocStats] -> SDoc
135 pprStatsLifetimes stats
136 = let lifeMap = foldl' plusUFM emptyUFM
137 [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
138 lifeBins = binLifetimeCount lifeMap
140 in ( text "-- vreg-population-lifetimes"
141 $$ text "-- (instruction_count, number_of_vregs_that_lived_that_long)"
142 $$ (vcat $ map ppr $ eltsUFM lifeBins)
145 binLifetimeCount :: UniqFM (Reg, Int) -> UniqFM (Int, Int)
147 = let lifes = map (\l -> (l, (l, 1)))
152 (\(l1, c1) (l2, c2) -> (l1, c1 + c2))
157 -- | Dump a table of how many conflicts vregs tend to have in the initial code.
159 :: [RegAllocStats] -> SDoc
161 pprStatsConflict stats
162 = let confMap = foldl' (plusUFM_C (\(c1, n1) (c2, n2) -> (c1, n1 + n2)))
164 $ map Color.slurpNodeConflictCount
165 [ raGraph s | s@RegAllocStatsStart{} <- stats ]
167 in ( text "-- vreg-conflicts"
168 $$ text "-- (conflict_count, number_of_vregs_that_had_that_many_conflicts)"
169 $$ (vcat $ map ppr $ eltsUFM confMap)
173 -- | For every vreg, dump it's how many conflicts it has and its lifetime
174 -- good for making a scatter plot.
177 -> Color.Graph Reg RegClass Reg -- ^ global register conflict graph
180 pprStatsLifeConflict stats graph
181 = let lifeMap = foldl' plusUFM emptyUFM
182 [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
184 scatter = map (\r -> let lifetime = case lookupUFM lifeMap r of
187 Just node = Color.lookupNode graph r
188 in parens $ hcat $ punctuate (text ", ")
189 [ doubleQuotes $ ppr $ Color.nodeId node
190 , ppr $ sizeUniqSet (Color.nodeConflicts node)
194 $ Color.graphMap graph
196 in ( text "-- vreg-conflict-lifetime"
197 $$ text "-- (vreg, vreg_conflicts, vreg_lifetime)"
203 -- Register colors for drawing conflict graphs
204 -- Keep this out of MachRegs.hs because it's specific to the graph coloring allocator.
207 -- reg colors for x86
209 regDotColor :: Reg -> SDoc
211 = let Just str = lookupUFM regColors reg
226 , (fake5, "#5500ff") ]
230 -- reg colors for x86_64
231 #if x86_64_TARGET_ARCH
232 regDotColor :: Reg -> SDoc
234 = let Just str = lookupUFM regColors reg
239 $ [ (rax, "#00ff00"), (eax, "#00ff00")
240 , (rbx, "#0000ff"), (ebx, "#0000ff")
241 , (rcx, "#00ffff"), (ecx, "#00ffff")
242 , (rdx, "#0080ff"), (edx, "#00ffff")
252 ++ zip (map RealReg [16..31]) (repeat "red")
256 -- reg colors for ppc
257 #if powerpc_TARGET_ARCH
258 regDotColor :: Reg -> SDoc
260 = case regClass reg of
261 RcInteger -> text "blue"
262 RcFloat -> text "red"
268 = let rs = padL 2 '0' (showHex r "")
269 gs = padL 2 '0' (showHex r "")
270 bs = padL 2 '0' (showHex r "")
273 = replicate (n - length s) c ++ s
274 in "#" ++ rs ++ gs ++ bs