PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/utils/GraphColor.hs

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