summaryrefslogtreecommitdiff
path: root/compiler/utils
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils')
-rw-r--r--compiler/utils/Digraph.hs15
-rw-r--r--compiler/utils/UniqFM.hs12
2 files changed, 25 insertions, 2 deletions
diff --git a/compiler/utils/Digraph.hs b/compiler/utils/Digraph.hs
index 2c90c1e41e..1d6ef24e61 100644
--- a/compiler/utils/Digraph.hs
+++ b/compiler/utils/Digraph.hs
@@ -94,6 +94,7 @@ type Node key payload = (payload, key, [key])
emptyGraph :: Graph a
emptyGraph = Graph (array (1, 0) []) (error "emptyGraph") (const Nothing)
+-- See Note [Deterministic SCC]
graphFromEdgedVertices
:: Ord key -- We only use Ord for efficiency,
-- it doesn't effect the result, so
@@ -200,6 +201,18 @@ depend on earlier ones, but not vice versa i.e. later components only have
edges going from them to earlier ones.
-}
+{-
+Note [Deterministic SCC]
+~~~~~~~~~~~~~~~~~~~~~~~~
+stronglyConnCompFromEdgedVertices and stronglyConnCompFromEdgedVerticesR
+provide a following guarantee:
+Given a deterministically ordered list of nodes it returns a deterministically
+ordered list of strongly connected components, where the list of vertices
+in an SCC is also deterministically ordered.
+Note that the order of edges doesn't need to be deterministic for this to work.
+We use the order of nodes to normalize the order of edges.
+-}
+
stronglyConnCompG :: Graph node -> [SCC node]
stronglyConnCompG graph = decodeSccs graph forest
where forest = {-# SCC "Digraph.scc" #-} scc (gr_int_graph graph)
@@ -216,6 +229,7 @@ decodeSccs Graph { gr_int_graph = graph, gr_vertex_to_node = vertex_fn } forest
-- The following two versions are provided for backwards compatability:
+-- See Note [Deterministic SCC]
stronglyConnCompFromEdgedVertices
:: Ord key
=> [Node key payload]
@@ -226,6 +240,7 @@ stronglyConnCompFromEdgedVertices
-- The "R" interface is used when you expect to apply SCC to
-- (some of) the result of SCC, so you dont want to lose the dependency info
+-- See Note [Deterministic SCC]
stronglyConnCompFromEdgedVerticesR
:: Ord key
=> [Node key payload]
diff --git a/compiler/utils/UniqFM.hs b/compiler/utils/UniqFM.hs
index 590358ab40..2ff635268d 100644
--- a/compiler/utils/UniqFM.hs
+++ b/compiler/utils/UniqFM.hs
@@ -61,7 +61,7 @@ module UniqFM (
isNullUFM,
lookupUFM, lookupUFM_Directly,
lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
- nonDetEltsUFM, eltsUFM, keysUFM, splitUFM,
+ nonDetEltsUFM, eltsUFM, nonDetKeysUFM, keysUFM, splitUFM,
ufmToSet_Directly,
ufmToList, ufmToIntMap,
joinUFM, pprUniqFM, pprUFM, pluralUFM
@@ -303,10 +303,18 @@ anyUFM p (UFM m) = M.fold ((||) . p) False m
allUFM :: (elt -> Bool) -> UniqFM elt -> Bool
allUFM p (UFM m) = M.fold ((&&) . p) True m
--- See Note [Deterministic UniqFM] to learn about nondeterminism
+-- See Note [Deterministic UniqFM] to learn about nondeterminism.
+-- If you use this please provide a justification why it doesn't introduce
+-- nondeterminism.
nonDetEltsUFM :: UniqFM elt -> [elt]
nonDetEltsUFM (UFM m) = M.elems m
+-- See Note [Deterministic UniqFM] to learn about nondeterminism.
+-- If you use this please provide a justification why it doesn't introduce
+-- nondeterminism.
+nonDetKeysUFM :: UniqFM elt -> [Unique]
+nonDetKeysUFM (UFM m) = map getUnique $ M.keys m
+
ufmToIntMap :: UniqFM elt -> M.IntMap elt
ufmToIntMap (UFM m) = m