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
35 { raLiveCmm :: [LiveCmmTop] -- ^ initial code, with liveness
36 , raGraph :: Color.Graph Reg RegClass Reg -- ^ the initial, uncolored graph
37 , raLifetimes :: UniqFM (Reg, Int) } -- ^ number of instrs each reg lives for
41 { raGraph :: Color.Graph Reg RegClass Reg -- ^ the partially colored graph
42 , raSpillStats :: SpillStats -- ^ spiller stats
43 , raLifetimes :: UniqFM (Reg, Int) -- ^ number of instrs each reg lives for
44 , raSpilled :: [LiveCmmTop] } -- ^ code with spill instructions added
46 -- a successful coloring
47 | RegAllocStatsColored
48 { raGraph :: Color.Graph Reg RegClass Reg -- ^ the colored graph
49 , raPatchedCmm :: [LiveCmmTop] } -- ^ code after register allocation
52 instance Outputable RegAllocStats where
54 ppr (s@RegAllocStatsStart{})
56 $$ text "# Native code with liveness information."
59 $$ text "# Initial register conflict graph."
60 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
62 ppr (s@RegAllocStatsSpill{})
64 $$ text "# Register conflict graph."
65 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
67 $$ text "# Spills inserted."
68 $$ ppr (raSpillStats s)
70 $$ text "# Code with spills inserted."
71 $$ (ppr (raSpilled s))
73 ppr (s@RegAllocStatsColored{})
75 $$ text "# Register conflict graph."
76 $$ Color.dotGraph regDotColor trivColorable (raGraph s)
78 $$ text "# Native code after register allocation."
79 $$ ppr (raPatchedCmm s)
82 -- | Do all the different analysis on this list of RegAllocStats
83 pprStats :: [RegAllocStats] -> Color.Graph Reg RegClass Reg -> SDoc
85 = let outSpills = pprStatsSpills stats
86 outLife = pprStatsLifetimes stats
87 outConflict = pprStatsConflict stats
88 outScatter = pprStatsLifeConflict stats graph
90 in vcat [outSpills, outLife, outConflict, outScatter]
93 -- | Dump a table of how many spill loads / stores were inserted for each vreg.
95 :: [RegAllocStats] -> SDoc
98 = let -- slurp out the stats from all the spiller stages
99 spillStats = [ s | s@RegAllocStatsSpill{} <- stats]
101 -- build a map of how many spill load/stores were inserted for each vreg
102 spillSL = foldl' (plusUFM_C accSpillSL) emptyUFM
103 $ map (spillStoreLoad . raSpillStats) spillStats
105 -- print the count of load/spills as a tuple so we can read back from the file easilly
106 pprSpillSL (r, loads, stores)
107 = (parens $ (hcat $ punctuate (text ", ") [doubleQuotes (ppr r), int loads, int stores]))
109 -- sum up the total number of spill instructions inserted
110 spillList = eltsUFM spillSL
111 spillTotal = foldl' (\(s1, l1) (s2, l2) -> (s1 + s2, l1 + l2))
113 $ map (\(n, s, l) -> (s, l))
116 in ( text "-- spills-added-total"
117 $$ text "-- (stores, loads)"
120 $$ text "-- spills-added"
121 $$ text "-- (reg_name, stores, loads)"
122 $$ (vcat $ map pprSpillSL $ spillList)
126 -- | Dump a table of how long vregs tend to live for in the initial code.
128 :: [RegAllocStats] -> SDoc
130 pprStatsLifetimes stats
131 = let lifeMap = foldl' plusUFM emptyUFM
132 [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
133 lifeBins = binLifetimeCount lifeMap
135 in ( text "-- vreg-population-lifetimes"
136 $$ text "-- (instruction_count, number_of_vregs_that_lived_that_long)"
137 $$ (vcat $ map ppr $ eltsUFM lifeBins)
140 binLifetimeCount :: UniqFM (Reg, Int) -> UniqFM (Int, Int)
142 = let lifes = map (\l -> (l, (l, 1)))
147 (\(l1, c1) (l2, c2) -> (l1, c1 + c2))
152 -- | Dump a table of how many conflicts vregs tend to have in the initial code.
154 :: [RegAllocStats] -> SDoc
156 pprStatsConflict stats
157 = let confMap = foldl' (plusUFM_C (\(c1, n1) (c2, n2) -> (c1, n1 + n2)))
159 $ map Color.slurpNodeConflictCount
160 [ raGraph s | s@RegAllocStatsStart{} <- stats ]
162 in ( text "-- vreg-conflicts"
163 $$ text "-- (conflict_count, number_of_vregs_that_had_that_many_conflicts)"
164 $$ (vcat $ map ppr $ eltsUFM confMap)
168 -- | For every vreg, dump it's how many conflicts it has and its lifetime
169 -- good for making a scatter plot.
172 -> Color.Graph Reg RegClass Reg -- ^ global register conflict graph
175 pprStatsLifeConflict stats graph
176 = let lifeMap = foldl' plusUFM emptyUFM
177 [ raLifetimes s | s@RegAllocStatsStart{} <- stats ]
179 scatter = map (\r -> let Just (_, lifetime) = lookupUFM lifeMap r
180 Just node = Color.lookupNode graph r
181 in parens $ hcat $ punctuate (text ", ")
182 [ doubleQuotes $ ppr $ Color.nodeId node
183 , ppr $ sizeUniqSet (Color.nodeConflicts node)
187 $ Color.graphMap graph
189 in ( text "-- vreg-conflict-lifetime"
190 $$ text "-- (vreg, vreg_conflicts, vreg_lifetime)"
196 -- Register colors for drawing conflict graphs
197 -- Keep this out of MachRegs.hs because it's specific to the graph coloring allocator.
200 -- reg colors for x86
202 regDotColor :: Reg -> SDoc
204 = let Just str = lookupUFM regColors reg
219 , (fake5, "#5500ff") ]
223 -- reg colors for x86_64
224 #if x86_64_TARGET_ARCH
225 regDotColor :: Reg -> SDoc
227 = let Just str = lookupUFM regColors reg
232 $ [ (rax, "#00ff00"), (eax, "#00ff00")
233 , (rbx, "#0000ff"), (ebx, "#0000ff")
234 , (rcx, "#00ffff"), (ecx, "#00ffff")
235 , (rdx, "#0080ff"), (edx, "#00ffff")
245 ++ zip (map RealReg [16..31]) (repeat "red")
249 -- reg colors for ppc
250 #if powerpc_TARGET_ARCH
251 regDotColor :: Reg -> SDoc
253 = case regClass reg of
254 RcInteger -> text "blue"
255 RcFloat -> text "red"
261 = let rs = padL 2 '0' (showHex r "")
262 gs = padL 2 '0' (showHex r "")
263 bs = padL 2 '0' (showHex r "")
266 = replicate (n - length s) c ++ s
267 in "#" ++ rs ++ gs ++ bs