summaryrefslogtreecommitdiff
path: root/compiler/utils/Digraph.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/Digraph.hs')
-rw-r--r--compiler/utils/Digraph.hs127
1 files changed, 105 insertions, 22 deletions
diff --git a/compiler/utils/Digraph.hs b/compiler/utils/Digraph.hs
index 1d6ef24e61..93906b237a 100644
--- a/compiler/utils/Digraph.hs
+++ b/compiler/utils/Digraph.hs
@@ -3,7 +3,7 @@
{-# LANGUAGE CPP, ScopedTypeVariables #-}
module Digraph(
- Graph, graphFromEdgedVertices,
+ Graph, graphFromEdgedVerticesOrd, graphFromEdgedVerticesUniq,
SCC(..), Node, flattenSCC, flattenSCCs,
stronglyConnCompG,
@@ -17,7 +17,10 @@ module Digraph(
findCycle,
-- For backwards compatability with the simpler version of Digraph
- stronglyConnCompFromEdgedVertices, stronglyConnCompFromEdgedVerticesR,
+ stronglyConnCompFromEdgedVerticesOrd,
+ stronglyConnCompFromEdgedVerticesOrdR,
+ stronglyConnCompFromEdgedVerticesUniq,
+ stronglyConnCompFromEdgedVerticesUniqR,
) where
#include "HsVersions.h"
@@ -57,6 +60,8 @@ import qualified Data.Set as Set
import qualified Data.Graph as G
import Data.Graph hiding (Graph, Edge, transposeG, reachable)
import Data.Tree
+import Unique
+import UniqFM
{-
************************************************************************
@@ -96,29 +101,71 @@ 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
- -- it can be safely used with Unique's.
- => [Node key payload] -- The graph; its ok for the
+ :: ReduceFn key payload
+ -> [Node key payload] -- The graph; its ok for the
-- out-list to contain keys which arent
-- a vertex key, they are ignored
-> Graph (Node key payload)
-graphFromEdgedVertices [] = emptyGraph
-graphFromEdgedVertices edged_vertices = Graph graph vertex_fn (key_vertex . key_extractor)
+graphFromEdgedVertices _reduceFn [] = emptyGraph
+graphFromEdgedVertices reduceFn edged_vertices =
+ Graph graph vertex_fn (key_vertex . key_extractor)
where key_extractor (_, k, _) = k
- (bounds, vertex_fn, key_vertex, numbered_nodes) = reduceNodesIntoVertices edged_vertices key_extractor
+ (bounds, vertex_fn, key_vertex, numbered_nodes) =
+ reduceFn edged_vertices key_extractor
graph = array bounds [ (v, sort $ mapMaybe key_vertex ks)
| (v, (_, _, ks)) <- numbered_nodes]
-- We normalize outgoing edges by sorting on node order, so
-- that the result doesn't depend on the order of the edges
+-- See Note [Deterministic SCC]
+-- See Note [reduceNodesIntoVertices implementations]
+graphFromEdgedVerticesOrd
+ :: Ord key
+ => [Node key payload] -- The graph; its ok for the
+ -- out-list to contain keys which arent
+ -- a vertex key, they are ignored
+ -> Graph (Node key payload)
+graphFromEdgedVerticesOrd = graphFromEdgedVertices reduceNodesIntoVerticesOrd
+
+-- See Note [Deterministic SCC]
+-- See Note [reduceNodesIntoVertices implementations]
+graphFromEdgedVerticesUniq
+ :: Uniquable key
+ => [Node key payload] -- The graph; its ok for the
+ -- out-list to contain keys which arent
+ -- a vertex key, they are ignored
+ -> Graph (Node key payload)
+graphFromEdgedVerticesUniq = graphFromEdgedVertices reduceNodesIntoVerticesUniq
+
+type ReduceFn key payload =
+ [Node key payload] -> (Node key payload -> key) ->
+ (Bounds, Vertex -> Node key payload
+ , key -> Maybe Vertex, [(Vertex, Node key payload)])
+{-
+Note [reduceNodesIntoVertices implementations]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+reduceNodesIntoVertices is parameterized by the container type.
+This is to accomodate key types that don't have an Ord instance
+and hence preclude the use of Data.Map. An example of such type
+would be Unique, there's no way to implement Ord Unique
+deterministically.
+
+For such types, there's a version with a Uniquable constraint.
+This leaves us with two versions of every function that depends on
+reduceNodesIntoVertices, one with Ord constraint and the other with
+Uniquable constraint.
+For example: graphFromEdgedVerticesOrd and graphFromEdgedVerticesUniq.
+
+The Uniq version should be a tiny bit more efficient since it uses
+Data.IntMap internally.
+-}
reduceNodesIntoVertices
- :: Ord key
- => [node]
- -> (node -> key)
- -> (Bounds, Vertex -> node, key -> Maybe Vertex, [(Vertex, node)])
-reduceNodesIntoVertices nodes key_extractor = (bounds, (!) vertex_map, key_vertex, numbered_nodes)
+ :: ([(key, Vertex)] -> m)
+ -> (key -> m -> Maybe Vertex)
+ -> ReduceFn key payload
+reduceNodesIntoVertices fromList lookup nodes key_extractor =
+ (bounds, (!) vertex_map, key_vertex, numbered_nodes)
where
max_v = length nodes - 1
bounds = (0, max_v) :: (Vertex, Vertex)
@@ -128,9 +175,17 @@ reduceNodesIntoVertices nodes key_extractor = (bounds, (!) vertex_map, key_verte
numbered_nodes = zip [0..] nodes
vertex_map = array bounds numbered_nodes
- key_map = Map.fromList
+ key_map = fromList
[ (key_extractor node, v) | (v, node) <- numbered_nodes ]
- key_vertex k = Map.lookup k key_map
+ key_vertex k = lookup k key_map
+
+-- See Note [reduceNodesIntoVertices implementations]
+reduceNodesIntoVerticesOrd :: Ord key => ReduceFn key payload
+reduceNodesIntoVerticesOrd = reduceNodesIntoVertices Map.fromList Map.lookup
+
+-- See Note [reduceNodesIntoVertices implementations]
+reduceNodesIntoVerticesUniq :: Uniquable key => ReduceFn key payload
+reduceNodesIntoVerticesUniq = reduceNodesIntoVertices listToUFM (flip lookupUFM)
{-
************************************************************************
@@ -204,7 +259,10 @@ edges going from them to earlier ones.
{-
Note [Deterministic SCC]
~~~~~~~~~~~~~~~~~~~~~~~~
-stronglyConnCompFromEdgedVertices and stronglyConnCompFromEdgedVerticesR
+stronglyConnCompFromEdgedVerticesUniq,
+stronglyConnCompFromEdgedVerticesUniqR,
+stronglyConnCompFromEdgedVerticesOrd and
+stronglyConnCompFromEdgedVerticesOrdR
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
@@ -230,22 +288,47 @@ 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
+-- See Note [reduceNodesIntoVertices implementations]
+stronglyConnCompFromEdgedVerticesOrd
:: Ord key
=> [Node key payload]
-> [SCC payload]
-stronglyConnCompFromEdgedVertices
- = map (fmap get_node) . stronglyConnCompFromEdgedVerticesR
+stronglyConnCompFromEdgedVerticesOrd
+ = map (fmap get_node) . stronglyConnCompFromEdgedVerticesOrdR
+ where get_node (n, _, _) = n
+
+-- The following two versions are provided for backwards compatability:
+-- See Note [Deterministic SCC]
+-- See Note [reduceNodesIntoVertices implementations]
+stronglyConnCompFromEdgedVerticesUniq
+ :: Uniquable key
+ => [Node key payload]
+ -> [SCC payload]
+stronglyConnCompFromEdgedVerticesUniq
+ = map (fmap get_node) . stronglyConnCompFromEdgedVerticesUniqR
where get_node (n, _, _) = n
-- 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
+-- See Note [reduceNodesIntoVertices implementations]
+stronglyConnCompFromEdgedVerticesOrdR
:: Ord key
=> [Node key payload]
-> [SCC (Node key payload)]
-stronglyConnCompFromEdgedVerticesR = stronglyConnCompG . graphFromEdgedVertices
+stronglyConnCompFromEdgedVerticesOrdR =
+ stronglyConnCompG . graphFromEdgedVertices reduceNodesIntoVerticesOrd
+
+-- 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]
+-- See Note [reduceNodesIntoVertices implementations]
+stronglyConnCompFromEdgedVerticesUniqR
+ :: Uniquable key
+ => [Node key payload]
+ -> [SCC (Node key payload)]
+stronglyConnCompFromEdgedVerticesUniqR =
+ stronglyConnCompG . graphFromEdgedVertices reduceNodesIntoVerticesUniq
{-
************************************************************************