@@ -26,7 +26,7 @@ rustc_index::newtype_index! {
2626 struct PreorderIndex { }
2727}
2828
29- pub fn dominators < G : ControlFlowGraph > ( graph : G ) -> Dominators < G :: Node > {
29+ pub fn dominator_tree < G : ControlFlowGraph > ( graph : G ) -> DominatorTree < G :: Node > {
3030 // compute the post order index (rank) for each node
3131 let mut post_order_rank = IndexVec :: from_elem_n ( 0 , graph. num_nodes ( ) ) ;
3232
@@ -244,7 +244,7 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
244244
245245 let start_node = graph. start_node ( ) ;
246246 immediate_dominators[ start_node] = None ;
247- Dominators { start_node, post_order_rank, immediate_dominators }
247+ DominatorTree { start_node, post_order_rank, immediate_dominators }
248248}
249249
250250/// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -309,16 +309,18 @@ fn compress(
309309
310310/// Tracks the list of dominators for each node.
311311#[ derive( Clone , Debug ) ]
312- pub struct Dominators < N : Idx > {
312+ pub struct DominatorTree < N : Idx > {
313313 start_node : N ,
314314 post_order_rank : IndexVec < N , usize > ,
315315 // Even though we track only the immediate dominator of each node, it's
316316 // possible to get its full list of dominators by looking up the dominator
317317 // of each dominator. (See the `impl Iterator for Iter` definition).
318+ //
319+ // Note: immediate_dominators[root] is Some(root)!
318320 immediate_dominators : IndexVec < N , Option < N > > ,
319321}
320322
321- impl < Node : Idx > Dominators < Node > {
323+ impl < Node : Idx > DominatorTree < Node > {
322324 /// Returns true if node is reachable from the start node.
323325 pub fn is_reachable ( & self , node : Node ) -> bool {
324326 node == self . start_node || self . immediate_dominators [ node] . is_some ( )
@@ -333,12 +335,7 @@ impl<Node: Idx> Dominators<Node> {
333335 /// See the `impl Iterator for Iter` definition to understand how this works.
334336 pub fn dominators ( & self , node : Node ) -> Iter < ' _ , Node > {
335337 assert ! ( self . is_reachable( node) , "node {node:?} is not reachable" ) ;
336- Iter { dominators : self , node : Some ( node) }
337- }
338-
339- pub fn dominates ( & self , dom : Node , node : Node ) -> bool {
340- // FIXME -- could be optimized by using post-order-rank
341- self . dominators ( node) . any ( |n| n == dom)
338+ Iter { dom_tree : self , node : Some ( node) }
342339 }
343340
344341 /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
@@ -351,7 +348,7 @@ impl<Node: Idx> Dominators<Node> {
351348}
352349
353350pub struct Iter < ' dom , Node : Idx > {
354- dominators : & ' dom Dominators < Node > ,
351+ dom_tree : & ' dom DominatorTree < Node > ,
355352 node : Option < Node > ,
356353}
357354
@@ -360,10 +357,96 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
360357
361358 fn next ( & mut self ) -> Option < Self :: Item > {
362359 if let Some ( node) = self . node {
363- self . node = self . dominators . immediate_dominator ( node) ;
360+ self . node = self . dom_tree . immediate_dominator ( node) ;
364361 Some ( node)
365362 } else {
366363 None
367364 }
368365 }
369366}
367+
368+ #[ derive( Clone , Debug ) ]
369+ pub struct Dominators < Node : Idx > {
370+ time : IndexVec < Node , Time > ,
371+ }
372+
373+ /// Describes the number of vertices discovered at the time when processing of a particular vertex
374+ /// started and when it finished. Both values are zero for unreachable vertices.
375+ #[ derive( Copy , Clone , Default , Debug ) ]
376+ struct Time {
377+ start : u32 ,
378+ finish : u32 ,
379+ }
380+
381+ impl < Node : Idx > Dominators < Node > {
382+ pub fn dummy ( ) -> Self {
383+ Self { time : Default :: default ( ) }
384+ }
385+
386+ /// Returns true if `a` dominates `b`.
387+ ///
388+ /// # Panics
389+ ///
390+ /// Panics if `b` is unreachable.
391+ pub fn dominates ( & self , a : Node , b : Node ) -> bool {
392+ let a = self . time [ a] ;
393+ let b = self . time [ b] ;
394+ assert ! ( b. start != 0 , "node {b:?} is not reachable" ) ;
395+ a. start <= b. start && b. finish <= a. finish
396+ }
397+ }
398+
399+ pub fn dominators < N : Idx > ( tree : & DominatorTree < N > ) -> Dominators < N > {
400+ let DominatorTree { start_node, ref immediate_dominators, post_order_rank : _ } = * tree;
401+
402+ // Transpose the dominator tree edges, so that child nodes of vertex v are stored in
403+ // node[edges[v].start..edges[y].end].
404+ let mut edges: IndexVec < N , std:: ops:: Range < u32 > > =
405+ IndexVec :: from_elem ( 0 ..0 , immediate_dominators) ;
406+ for & idom in immediate_dominators. iter ( ) {
407+ if let Some ( idom) = idom {
408+ edges[ idom] . end += 1 ;
409+ }
410+ }
411+ let mut m = 0 ;
412+ for e in edges. iter_mut ( ) {
413+ m += e. end ;
414+ e. start = m;
415+ e. end = m;
416+ }
417+ let mut node = IndexVec :: from_elem_n ( Idx :: new ( 0 ) , m. try_into ( ) . unwrap ( ) ) ;
418+ for ( i, & idom) in immediate_dominators. iter_enumerated ( ) {
419+ if let Some ( idom) = idom {
420+ edges[ idom] . start -= 1 ;
421+ node[ edges[ idom] . start ] = i;
422+ }
423+ }
424+
425+ // Perform a depth-first search of the dominator tree. Record the number of vertices discovered
426+ // when vertex v is discovered first as time[v].start, and when its processing is finished as
427+ // time[v].finish.
428+ let mut time: IndexVec < N , Time > = IndexVec :: from_elem ( Time :: default ( ) , immediate_dominators) ;
429+ let mut stack = Vec :: new ( ) ;
430+
431+ let mut discovered = 1 ;
432+ stack. push ( start_node) ;
433+ time[ start_node] . start = discovered;
434+
435+ while let Some ( & i) = stack. last ( ) {
436+ let e = & mut edges[ i] ;
437+ if e. start == e. end {
438+ // Finish processing vertex i.
439+ time[ i] . finish = discovered;
440+ stack. pop ( ) ;
441+ } else {
442+ let j = node[ e. start ] ;
443+ e. start += 1 ;
444+ // Start processing vertex j.
445+ discovered += 1 ;
446+ time[ j] . start = discovered;
447+ stack. push ( j) ;
448+ }
449+ }
450+
451+ Dominators { time }
452+ }
0 commit comments