PageRenderTime 44ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/utils/GraphColor.hs

http://github.com/ghc/ghc
Haskell | 371 lines | 201 code | 69 blank | 101 comment | 12 complexity | 4361270a0406838756e440e83eab21bb MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0
  1. -- | Graph Coloring.
  2. -- This is a generic graph coloring library, abstracted over the type of
  3. -- the node keys, nodes and colors.
  4. --
  5. module GraphColor (
  6. module GraphBase,
  7. module GraphOps,
  8. module GraphPpr,
  9. colorGraph
  10. )
  11. where
  12. import GraphBase
  13. import GraphOps
  14. import GraphPpr
  15. import Unique
  16. import UniqFM
  17. import UniqSet
  18. import Outputable
  19. import Data.Maybe
  20. import Data.List
  21. -- | Try to color a graph with this set of colors.
  22. -- Uses Chaitin's algorithm to color the graph.
  23. -- The graph is scanned for nodes which are deamed 'trivially colorable'. These nodes
  24. -- are pushed onto a stack and removed from the graph.
  25. -- Once this process is complete the graph can be colored by removing nodes from
  26. -- the stack (ie in reverse order) and assigning them colors different to their neighbors.
  27. --
  28. colorGraph
  29. :: ( Uniquable k, Uniquable cls, Uniquable color
  30. , Eq cls, Ord k
  31. , Outputable k, Outputable cls, Outputable color)
  32. => Bool -- ^ whether to do iterative coalescing
  33. -> Int -- ^ how many times we've tried to color this graph so far.
  34. -> UniqFM (UniqSet color) -- ^ map of (node class -> set of colors available for this class).
  35. -> Triv k cls color -- ^ fn to decide whether a node is trivially colorable.
  36. -> (Graph k cls color -> k) -- ^ fn to choose a node to potentially leave uncolored if nothing is trivially colorable.
  37. -> Graph k cls color -- ^ the graph to color.
  38. -> ( Graph k cls color -- the colored graph.
  39. , UniqSet k -- the set of nodes that we couldn't find a color for.
  40. , UniqFM k ) -- map of regs (r1 -> r2) that were coaleced
  41. -- r1 should be replaced by r2 in the source
  42. colorGraph iterative spinCount colors triv spill graph0
  43. = let
  44. -- If we're not doing iterative coalescing then do an aggressive coalescing first time
  45. -- around and then conservative coalescing for subsequent passes.
  46. --
  47. -- Aggressive coalescing is a quick way to get rid of many reg-reg moves. However, if
  48. -- there is a lot of register pressure and we do it on every round then it can make the
  49. -- graph less colorable and prevent the algorithm from converging in a sensible number
  50. -- of cycles.
  51. --
  52. (graph_coalesced, kksCoalesce1)
  53. = if iterative
  54. then (graph0, [])
  55. else if spinCount == 0
  56. then coalesceGraph True triv graph0
  57. else coalesceGraph False triv graph0
  58. -- run the scanner to slurp out all the trivially colorable nodes
  59. -- (and do coalescing if iterative coalescing is enabled)
  60. (ksTriv, ksProblems, kksCoalesce2)
  61. = colorScan iterative triv spill graph_coalesced
  62. -- If iterative coalescing is enabled, the scanner will coalesce the graph as does its business.
  63. -- We need to apply all the coalescences found by the scanner to the original
  64. -- graph before doing assignColors.
  65. --
  66. -- Because we've got the whole, non-pruned graph here we turn on aggressive coalecing
  67. -- to force all the (conservative) coalescences found during scanning.
  68. --
  69. (graph_scan_coalesced, _)
  70. = mapAccumL (coalesceNodes True triv) graph_coalesced kksCoalesce2
  71. -- color the trivially colorable nodes
  72. -- during scanning, keys of triv nodes were added to the front of the list as they were found
  73. -- this colors them in the reverse order, as required by the algorithm.
  74. (graph_triv, ksNoTriv)
  75. = assignColors colors graph_scan_coalesced ksTriv
  76. -- try and color the problem nodes
  77. -- problem nodes are the ones that were left uncolored because they weren't triv.
  78. -- theres a change we can color them here anyway.
  79. (graph_prob, ksNoColor)
  80. = assignColors colors graph_triv ksProblems
  81. -- if the trivially colorable nodes didn't color then something is probably wrong
  82. -- with the provided triv function.
  83. --
  84. in if not $ null ksNoTriv
  85. then pprPanic "colorGraph: trivially colorable nodes didn't color!" -- empty
  86. ( empty
  87. $$ text "ksTriv = " <> ppr ksTriv
  88. $$ text "ksNoTriv = " <> ppr ksNoTriv
  89. $$ text "colors = " <> ppr colors
  90. $$ empty
  91. $$ dotGraph (\_ -> text "white") triv graph_triv)
  92. else ( graph_prob
  93. , mkUniqSet ksNoColor -- the nodes that didn't color (spills)
  94. , if iterative
  95. then (listToUFM kksCoalesce2)
  96. else (listToUFM kksCoalesce1))
  97. -- | Scan through the conflict graph separating out trivially colorable and
  98. -- potentially uncolorable (problem) nodes.
  99. --
  100. -- Checking whether a node is trivially colorable or not is a resonably expensive operation,
  101. -- so after a triv node is found and removed from the graph it's no good to return to the 'start'
  102. -- of the graph and recheck a bunch of nodes that will probably still be non-trivially colorable.
  103. --
  104. -- To ward against this, during each pass through the graph we collect up a list of triv nodes
  105. -- that were found, and only remove them once we've finished the pass. The more nodes we can delete
  106. -- at once the more likely it is that nodes we've already checked will become trivially colorable
  107. -- for the next pass.
  108. --
  109. -- TODO: add work lists to finding triv nodes is easier.
  110. -- If we've just scanned the graph, and removed triv nodes, then the only
  111. -- nodes that we need to rescan are the ones we've removed edges from.
  112. colorScan
  113. :: ( Uniquable k, Uniquable cls, Uniquable color
  114. , Ord k, Eq cls
  115. , Outputable k, Outputable cls)
  116. => Bool -- ^ whether to do iterative coalescing
  117. -> Triv k cls color -- ^ fn to decide whether a node is trivially colorable
  118. -> (Graph k cls color -> k) -- ^ fn to choose a node to potentially leave uncolored if nothing is trivially colorable.
  119. -> Graph k cls color -- ^ the graph to scan
  120. -> ([k], [k], [(k, k)]) -- triv colorable nodes, problem nodes, pairs of nodes to coalesce
  121. colorScan iterative triv spill graph
  122. = colorScan_spin iterative triv spill graph [] [] []
  123. colorScan_spin
  124. :: ( Uniquable k, Uniquable cls, Uniquable color
  125. , Ord k, Eq cls
  126. , Outputable k, Outputable cls)
  127. => Bool
  128. -> Triv k cls color
  129. -> (Graph k cls color -> k)
  130. -> Graph k cls color
  131. -> [k]
  132. -> [k]
  133. -> [(k, k)]
  134. -> ([k], [k], [(k, k)])
  135. colorScan_spin iterative triv spill graph
  136. ksTriv ksSpill kksCoalesce
  137. -- if the graph is empty then we're done
  138. | isNullUFM $ graphMap graph
  139. = (ksTriv, ksSpill, reverse kksCoalesce)
  140. -- Simplify:
  141. -- Look for trivially colorable nodes.
  142. -- If we can find some then remove them from the graph and go back for more.
  143. --
  144. | nsTrivFound@(_:_)
  145. <- scanGraph (\node -> triv (nodeClass node) (nodeConflicts node) (nodeExclusions node)
  146. -- for iterative coalescing we only want non-move related
  147. -- nodes here
  148. && (not iterative || isEmptyUniqSet (nodeCoalesce node)))
  149. $ graph
  150. , ksTrivFound <- map nodeId nsTrivFound
  151. , graph2 <- foldr (\k g -> let Just g' = delNode k g
  152. in g')
  153. graph ksTrivFound
  154. = colorScan_spin iterative triv spill graph2
  155. (ksTrivFound ++ ksTriv)
  156. ksSpill
  157. kksCoalesce
  158. -- Coalesce:
  159. -- If we're doing iterative coalescing and no triv nodes are available
  160. -- then it's time for a coalescing pass.
  161. | iterative
  162. = case coalesceGraph False triv graph of
  163. -- we were able to coalesce something
  164. -- go back to Simplify and see if this frees up more nodes to be trivially colorable.
  165. (graph2, kksCoalesceFound @(_:_))
  166. -> colorScan_spin iterative triv spill graph2
  167. ksTriv ksSpill (reverse kksCoalesceFound ++ kksCoalesce)
  168. -- Freeze:
  169. -- nothing could be coalesced (or was triv),
  170. -- time to choose a node to freeze and give up on ever coalescing it.
  171. (graph2, [])
  172. -> case freezeOneInGraph graph2 of
  173. -- we were able to freeze something
  174. -- hopefully this will free up something for Simplify
  175. (graph3, True)
  176. -> colorScan_spin iterative triv spill graph3
  177. ksTriv ksSpill kksCoalesce
  178. -- we couldn't find something to freeze either
  179. -- time for a spill
  180. (graph3, False)
  181. -> colorScan_spill iterative triv spill graph3
  182. ksTriv ksSpill kksCoalesce
  183. -- spill time
  184. | otherwise
  185. = colorScan_spill iterative triv spill graph
  186. ksTriv ksSpill kksCoalesce
  187. -- Select:
  188. -- we couldn't find any triv nodes or things to freeze or coalesce,
  189. -- and the graph isn't empty yet.. We'll have to choose a spill
  190. -- candidate and leave it uncolored.
  191. --
  192. colorScan_spill
  193. :: ( Uniquable k, Uniquable cls, Uniquable color
  194. , Ord k, Eq cls
  195. , Outputable k, Outputable cls)
  196. => Bool
  197. -> Triv k cls color
  198. -> (Graph k cls color -> k)
  199. -> Graph k cls color
  200. -> [k]
  201. -> [k]
  202. -> [(k, k)]
  203. -> ([k], [k], [(k, k)])
  204. colorScan_spill iterative triv spill graph
  205. ksTriv ksSpill kksCoalesce
  206. = let kSpill = spill graph
  207. Just graph' = delNode kSpill graph
  208. in colorScan_spin iterative triv spill graph'
  209. ksTriv (kSpill : ksSpill) kksCoalesce
  210. -- | Try to assign a color to all these nodes.
  211. assignColors
  212. :: ( Uniquable k, Uniquable cls, Uniquable color
  213. , Outputable cls)
  214. => UniqFM (UniqSet color) -- ^ map of (node class -> set of colors available for this class).
  215. -> Graph k cls color -- ^ the graph
  216. -> [k] -- ^ nodes to assign a color to.
  217. -> ( Graph k cls color -- the colored graph
  218. , [k]) -- the nodes that didn't color.
  219. assignColors colors graph ks
  220. = assignColors' colors graph [] ks
  221. where assignColors' _ graph prob []
  222. = (graph, prob)
  223. assignColors' colors graph prob (k:ks)
  224. = case assignColor colors k graph of
  225. -- couldn't color this node
  226. Nothing -> assignColors' colors graph (k : prob) ks
  227. -- this node colored ok, so do the rest
  228. Just graph' -> assignColors' colors graph' prob ks
  229. assignColor colors u graph
  230. | Just c <- selectColor colors graph u
  231. = Just (setColor u c graph)
  232. | otherwise
  233. = Nothing
  234. -- | Select a color for a certain node
  235. -- taking into account preferences, neighbors and exclusions.
  236. -- returns Nothing if no color can be assigned to this node.
  237. --
  238. selectColor
  239. :: ( Uniquable k, Uniquable cls, Uniquable color
  240. , Outputable cls)
  241. => UniqFM (UniqSet color) -- ^ map of (node class -> set of colors available for this class).
  242. -> Graph k cls color -- ^ the graph
  243. -> k -- ^ key of the node to select a color for.
  244. -> Maybe color
  245. selectColor colors graph u
  246. = let -- lookup the node
  247. Just node = lookupNode graph u
  248. -- lookup the available colors for the class of this node.
  249. colors_avail
  250. = case lookupUFM colors (nodeClass node) of
  251. Nothing -> pprPanic "selectColor: no colors available for class " (ppr (nodeClass node))
  252. Just cs -> cs
  253. -- find colors we can't use because they're already being used
  254. -- by a node that conflicts with this one.
  255. Just nsConflicts
  256. = sequence
  257. $ map (lookupNode graph)
  258. $ nonDetEltsUFM
  259. $ nodeConflicts node
  260. -- See Note [Unique Determinism and code generation]
  261. colors_conflict = mkUniqSet
  262. $ catMaybes
  263. $ map nodeColor nsConflicts
  264. -- the prefs of our neighbors
  265. colors_neighbor_prefs
  266. = mkUniqSet
  267. $ concat $ map nodePreference nsConflicts
  268. -- colors that are still valid for us
  269. colors_ok_ex = minusUniqSet colors_avail (nodeExclusions node)
  270. colors_ok = minusUniqSet colors_ok_ex colors_conflict
  271. -- the colors that we prefer, and are still ok
  272. colors_ok_pref = intersectUniqSets
  273. (mkUniqSet $ nodePreference node) colors_ok
  274. -- the colors that we could choose while being nice to our neighbors
  275. colors_ok_nice = minusUniqSet
  276. colors_ok colors_neighbor_prefs
  277. -- the best of all possible worlds..
  278. colors_ok_pref_nice
  279. = intersectUniqSets
  280. colors_ok_nice colors_ok_pref
  281. -- make the decision
  282. chooseColor
  283. -- everyone is happy, yay!
  284. | not $ isEmptyUniqSet colors_ok_pref_nice
  285. , c : _ <- filter (\x -> elementOfUniqSet x colors_ok_pref_nice)
  286. (nodePreference node)
  287. = Just c
  288. -- we've got one of our preferences
  289. | not $ isEmptyUniqSet colors_ok_pref
  290. , c : _ <- filter (\x -> elementOfUniqSet x colors_ok_pref)
  291. (nodePreference node)
  292. = Just c
  293. -- it wasn't a preference, but it was still ok
  294. | not $ isEmptyUniqSet colors_ok
  295. , c : _ <- nonDetEltsUFM colors_ok
  296. -- See Note [Unique Determinism and code generation]
  297. = Just c
  298. -- no colors were available for us this time.
  299. -- looks like we're going around the loop again..
  300. | otherwise
  301. = Nothing
  302. in chooseColor