@@ -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 dominators < G : ControlFlowGraph > ( graph : & G ) -> Dominators < 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,10 @@ 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+
248+ let time = compute_access_time ( start_node, & immediate_dominators) ;
249+
250+ Dominators { start_node, post_order_rank, immediate_dominators, time }
248251}
249252
250253/// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -316,6 +319,7 @@ pub struct Dominators<N: Idx> {
316319 // possible to get its full list of dominators by looking up the dominator
317320 // of each dominator. (See the `impl Iterator for Iter` definition).
318321 immediate_dominators : IndexVec < N , Option < N > > ,
322+ time : IndexVec < N , Time > ,
319323}
320324
321325impl < Node : Idx > Dominators < Node > {
@@ -333,12 +337,7 @@ impl<Node: Idx> Dominators<Node> {
333337 /// See the `impl Iterator for Iter` definition to understand how this works.
334338 pub fn dominators ( & self , node : Node ) -> Iter < ' _ , Node > {
335339 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)
340+ Iter { dom_tree : self , node : Some ( node) }
342341 }
343342
344343 /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
@@ -348,10 +347,22 @@ impl<Node: Idx> Dominators<Node> {
348347 pub fn rank_partial_cmp ( & self , lhs : Node , rhs : Node ) -> Option < Ordering > {
349348 self . post_order_rank [ rhs] . partial_cmp ( & self . post_order_rank [ lhs] )
350349 }
350+
351+ /// Returns true if `a` dominates `b`.
352+ ///
353+ /// # Panics
354+ ///
355+ /// Panics if `b` is unreachable.
356+ pub fn dominates ( & self , a : Node , b : Node ) -> bool {
357+ let a = self . time [ a] ;
358+ let b = self . time [ b] ;
359+ assert ! ( b. start != 0 , "node {b:?} is not reachable" ) ;
360+ a. start <= b. start && b. finish <= a. finish
361+ }
351362}
352363
353364pub struct Iter < ' dom , Node : Idx > {
354- dominators : & ' dom Dominators < Node > ,
365+ dom_tree : & ' dom Dominators < Node > ,
355366 node : Option < Node > ,
356367}
357368
@@ -360,10 +371,74 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
360371
361372 fn next ( & mut self ) -> Option < Self :: Item > {
362373 if let Some ( node) = self . node {
363- self . node = self . dominators . immediate_dominator ( node) ;
374+ self . node = self . dom_tree . immediate_dominator ( node) ;
364375 Some ( node)
365376 } else {
366377 None
367378 }
368379 }
369380}
381+
382+ /// Describes the number of vertices discovered at the time when processing of a particular vertex
383+ /// started and when it finished. Both values are zero for unreachable vertices.
384+ #[ derive( Copy , Clone , Default , Debug ) ]
385+ struct Time {
386+ start : u32 ,
387+ finish : u32 ,
388+ }
389+
390+ fn compute_access_time < N : Idx > (
391+ start_node : N ,
392+ immediate_dominators : & IndexSlice < N , Option < N > > ,
393+ ) -> IndexVec < N , Time > {
394+ // Transpose the dominator tree edges, so that child nodes of vertex v are stored in
395+ // node[edges[v].start..edges[v].end].
396+ let mut edges: IndexVec < N , std:: ops:: Range < u32 > > =
397+ IndexVec :: from_elem ( 0 ..0 , immediate_dominators) ;
398+ for & idom in immediate_dominators. iter ( ) {
399+ if let Some ( idom) = idom {
400+ edges[ idom] . end += 1 ;
401+ }
402+ }
403+ let mut m = 0 ;
404+ for e in edges. iter_mut ( ) {
405+ m += e. end ;
406+ e. start = m;
407+ e. end = m;
408+ }
409+ let mut node = IndexVec :: from_elem_n ( Idx :: new ( 0 ) , m. try_into ( ) . unwrap ( ) ) ;
410+ for ( i, & idom) in immediate_dominators. iter_enumerated ( ) {
411+ if let Some ( idom) = idom {
412+ edges[ idom] . start -= 1 ;
413+ node[ edges[ idom] . start ] = i;
414+ }
415+ }
416+
417+ // Perform a depth-first search of the dominator tree. Record the number of vertices discovered
418+ // when vertex v is discovered first as time[v].start, and when its processing is finished as
419+ // time[v].finish.
420+ let mut time: IndexVec < N , Time > = IndexVec :: from_elem ( Time :: default ( ) , immediate_dominators) ;
421+ let mut stack = Vec :: new ( ) ;
422+
423+ let mut discovered = 1 ;
424+ stack. push ( start_node) ;
425+ time[ start_node] . start = discovered;
426+
427+ while let Some ( & i) = stack. last ( ) {
428+ let e = & mut edges[ i] ;
429+ if e. start == e. end {
430+ // Finish processing vertex i.
431+ time[ i] . finish = discovered;
432+ stack. pop ( ) ;
433+ } else {
434+ let j = node[ e. start ] ;
435+ e. start += 1 ;
436+ // Start processing vertex j.
437+ discovered += 1 ;
438+ time[ j] . start = discovered;
439+ stack. push ( j) ;
440+ }
441+ }
442+
443+ time
444+ }
0 commit comments