@@ -51,7 +51,9 @@ type Preds = Vector [Int]
5151immediateDominators :: (Graph g ) => g -> Vertex -> [(Vertex , Vertex )]
5252immediateDominators g root = fromMaybe [] $ do
5353 (res, toNode, _) <- domWork g root
54- return $ tail $ V. toList $ V. imap (\ i n -> (toNode! i, toNode! n)) res
54+ case V. toList $ V. imap (\ i n -> (toNode! i, toNode! n)) res of
55+ [] -> error " Impossible: a vertex always dominates itself"
56+ _ : rest -> return rest
5557
5658-- | Compute all of the dominators for each 'Vertex' reachable from the @root@.
5759-- Each reachable 'Vertex' is paired with the list of nodes that dominate it,
@@ -66,38 +68,43 @@ dominators g root = fromMaybe [] $ do
6668 [(n, verts) | n <- rest]
6769
6870domWork :: (Graph g ) => g -> Vertex -> Maybe (IDom , ToNode , FromNode )
69- domWork g root
70- | null trees = Nothing
71- | otherwise = return (idom, toNode, fromNode)
71+ domWork g root =
72+ -- Build up a depth-first tree from the root as a first approximation
73+ case dff g [root] of
74+ [] -> Nothing
75+ [tree] ->
76+ let (s, ntree) = numberTree 0 tree
77+ -- Start with an approximation (idom0) where the idom of each node is
78+ -- its parent in the depth-first tree. Note that index 0 is the root,
79+ -- which we will basically be ignoring (since it has no dominator).
80+ dom0Map = M. fromList (treeEdges (- 1 ) ntree)
81+ idom0 = V. generate (M. size dom0Map) (dom0Map M. ! )
82+ -- Build a mapping from graph vertices to internal indices. @treeNodes@
83+ -- are nodes that are in the depth-first tree from the root. @otherNodes@
84+ -- are the rest of the nodes in the graph, mapped to -1 (since they aren't
85+ -- going to be in the result)
86+ treeNodes = M. fromList $ zip (T. flatten tree) (T. flatten ntree)
87+ otherNodes = M. fromList $ zip vlist (repeat (- 1 ))
88+ fromNode = M. unionWith const treeNodes otherNodes
89+
90+ -- Translate from internal nodes back to graph nodes (only need the nodes
91+ -- in the depth-first tree)
92+ toNodeMap = M. fromList $ zip (T. flatten ntree) (T. flatten tree)
93+ toNode = V. generate (M. size toNodeMap) (toNodeMap M. ! )
94+
95+ -- Use a pre-pass over the graph to collect predecessors so that we don't
96+ -- require a Bidirectional graph. We need a linear pass over the graph
97+ -- here anyway, so we don't lose anything.
98+ predMap = fmap S. toList $ foldr (toPredecessor g) M. empty vlist
99+ preds = V. fromList $ [0 ] : [filter (/= - 1 ) (map (fromNode M. ! ) (predMap M. ! (toNode ! i)))
100+ | i <- [1 .. s- 1 ]]
101+
102+
103+ idom = fixEq (refineIDom preds) idom0
104+ in return (idom, toNode, fromNode)
105+ _trees -> error " Impossible: only a single tree can be reachable starting from a single root node"
72106 where
73107 vlist = reachable root g
74- -- Build up a depth-first tree from the root as a first approximation
75- trees@ (~ [tree]) = dff g [root]
76- (s, ntree) = numberTree 0 tree
77- -- Start with an approximation (idom0) where the idom of each node is
78- -- its parent in the depth-first tree. Note that index 0 is the root,
79- -- which we will basically be ignoring (since it has no dominator).
80- dom0Map = M. fromList (treeEdges (- 1 ) ntree)
81- idom0 = V. generate (M. size dom0Map) (dom0Map M. ! )
82- -- Build a mapping from graph vertices to internal indices. @treeNodes@
83- -- are nodes that are in the depth-first tree from the root. @otherNodes@
84- -- are the rest of the nodes in the graph, mapped to -1 (since they aren't
85- -- going to be in the result)
86- treeNodes = M. fromList $ zip (T. flatten tree) (T. flatten ntree)
87- otherNodes = M. fromList $ zip vlist (repeat (- 1 ))
88- fromNode = M. unionWith const treeNodes otherNodes
89- -- Translate from internal nodes back to graph nodes (only need the nodes
90- -- in the depth-first tree)
91- toNodeMap = M. fromList $ zip (T. flatten ntree) (T. flatten tree)
92- toNode = V. generate (M. size toNodeMap) (toNodeMap M. ! )
93-
94- -- Use a pre-pass over the graph to collect predecessors so that we don't
95- -- require a Bidirectional graph. We need a linear pass over the graph
96- -- here anyway, so we don't lose anything.
97- predMap = fmap S. toList $ foldr (toPredecessor g) M. empty vlist
98- preds = V. fromList $ [0 ] : [filter (/= - 1 ) (map (fromNode M. ! ) (predMap M. ! (toNode ! i)))
99- | i <- [1 .. s- 1 ]]
100- idom = fixEq (refineIDom preds) idom0
101108
102109toPredecessor :: (Graph g )
103110 => g
0 commit comments