PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/ghc-7.0.4/compiler/utils/GraphColor.hs

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