@@ -25,7 +25,7 @@ rustc_index::newtype_index! {
2525 struct PreorderIndex { }
2626}
2727
28- pub fn dominators < G : ControlFlowGraph > ( graph : G ) -> Dominators < G :: Node > {
28+ pub fn dominator_tree < G : ControlFlowGraph > ( graph : G ) -> DominatorTree < G :: Node > {
2929 // compute the post order index (rank) for each node
3030 let mut post_order_rank = IndexVec :: from_elem_n ( 0 , graph. num_nodes ( ) ) ;
3131
@@ -201,7 +201,7 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
201201 immediate_dominators[ * node] = Some ( pre_order_to_real[ idom[ idx] ] ) ;
202202 }
203203
204- Dominators { post_order_rank, immediate_dominators }
204+ DominatorTree { post_order_rank, immediate_dominators }
205205}
206206
207207/// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -265,13 +265,14 @@ fn compress(
265265}
266266
267267#[ derive( Clone , Debug ) ]
268- pub struct Dominators < N : Idx > {
268+ pub struct DominatorTree < N : Idx > {
269269 post_order_rank : IndexVec < N , usize > ,
270+ // Note: immediate_dominators[root] is Some(root)!
270271 immediate_dominators : IndexVec < N , Option < N > > ,
271272}
272273
273- impl < Node : Idx > Dominators < Node > {
274- pub fn is_reachable ( & self , node : Node ) -> bool {
274+ impl < Node : Idx > DominatorTree < Node > {
275+ fn is_reachable ( & self , node : Node ) -> bool {
275276 self . immediate_dominators [ node] . is_some ( )
276277 }
277278
@@ -282,25 +283,12 @@ impl<Node: Idx> Dominators<Node> {
282283
283284 pub fn dominators ( & self , node : Node ) -> Iter < ' _ , Node > {
284285 assert ! ( self . is_reachable( node) , "node {node:?} is not reachable" ) ;
285- Iter { dominators : self , node : Some ( node) }
286- }
287-
288- pub fn dominates ( & self , dom : Node , node : Node ) -> bool {
289- // FIXME -- could be optimized by using post-order-rank
290- self . dominators ( node) . any ( |n| n == dom)
291- }
292-
293- /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
294- /// relationship, the dominator will always precede the dominated. (The relative ordering
295- /// of two unrelated nodes will also be consistent, but otherwise the order has no
296- /// meaning.) This method cannot be used to determine if either Node dominates the other.
297- pub fn rank_partial_cmp ( & self , lhs : Node , rhs : Node ) -> Option < Ordering > {
298- self . post_order_rank [ rhs] . partial_cmp ( & self . post_order_rank [ lhs] )
286+ Iter { dom_tree : self , node : Some ( node) }
299287 }
300288}
301289
302290pub struct Iter < ' dom , Node : Idx > {
303- dominators : & ' dom Dominators < Node > ,
291+ dom_tree : & ' dom DominatorTree < Node > ,
304292 node : Option < Node > ,
305293}
306294
@@ -309,7 +297,7 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
309297
310298 fn next ( & mut self ) -> Option < Self :: Item > {
311299 if let Some ( node) = self . node {
312- let dom = self . dominators . immediate_dominator ( node) ;
300+ let dom = self . dom_tree . immediate_dominator ( node) ;
313301 if dom == node {
314302 self . node = None ; // reached the root
315303 } else {
@@ -321,3 +309,101 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
321309 }
322310 }
323311}
312+
313+ #[ derive( Clone , Debug ) ]
314+ pub struct Dominators < Node : Idx > {
315+ time : IndexVec < Node , Time > ,
316+ post_order_rank : IndexVec < Node , usize > ,
317+ }
318+
319+ /// Describes the number of vertices discovered at the time when processing of a particular vertex
320+ /// started and when it finished. Both values are zero for unreachable vertices.
321+ #[ derive( Copy , Clone , Default , Debug ) ]
322+ struct Time {
323+ start : u32 ,
324+ finish : u32 ,
325+ }
326+
327+ impl < Node : Idx > Dominators < Node > {
328+ pub fn dummy ( ) -> Self {
329+ Self { time : Default :: default ( ) , post_order_rank : Default :: default ( ) }
330+ }
331+
332+ /// Returns true if `a` dominates `b`.
333+ ///
334+ /// # Panics
335+ ///
336+ /// Panics if `b` is unreachable.
337+ pub fn dominates ( & self , a : Node , b : Node ) -> bool {
338+ let a = self . time [ a] ;
339+ let b = self . time [ b] ;
340+ assert ! ( b. start != 0 , "node {b:?} is not reachable" ) ;
341+ a. start <= b. start && b. finish <= a. finish
342+ }
343+
344+ /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
345+ /// relationship, the dominator will always precede the dominated. (The relative ordering
346+ /// of two unrelated nodes will also be consistent, but otherwise the order has no
347+ /// meaning.) This method cannot be used to determine if either Node dominates the other.
348+ pub fn rank_partial_cmp ( & self , lhs : Node , rhs : Node ) -> Option < Ordering > {
349+ self . post_order_rank [ rhs] . partial_cmp ( & self . post_order_rank [ lhs] )
350+ }
351+ }
352+
353+ pub fn dominators < G : Copy + ControlFlowGraph > ( graph : G ) -> Dominators < G :: Node > {
354+ let DominatorTree { mut immediate_dominators, post_order_rank } = dominator_tree ( graph) ;
355+
356+ immediate_dominators[ graph. start_node ( ) ] = None ;
357+
358+ // Transpose the dominator tree edges, so that child nodes of vertex v are stored in
359+ // node[edges[v].start..edges[y].end].
360+ let mut edges: IndexVec < G :: Node , std:: ops:: Range < u32 > > =
361+ IndexVec :: from_elem_n ( 0 ..0 , graph. num_nodes ( ) ) ;
362+ for & idom in immediate_dominators. iter ( ) {
363+ if let Some ( idom) = idom {
364+ edges[ idom] . end += 1 ;
365+ }
366+ }
367+ let mut m = 0 ;
368+ for e in edges. iter_mut ( ) {
369+ m += e. end ;
370+ e. start = m;
371+ e. end = m;
372+ }
373+ let mut node = IndexVec :: from_elem_n ( Idx :: new ( 0 ) , m. try_into ( ) . unwrap ( ) ) ;
374+ for ( i, & idom) in immediate_dominators. iter_enumerated ( ) {
375+ if let Some ( idom) = idom {
376+ edges[ idom] . start -= 1 ;
377+ node[ edges[ idom] . start ] = i;
378+ }
379+ }
380+
381+ // Perform a depth-first search of the dominator tree. Record the number of vertices discovered
382+ // when vertex v is discovered first as time[v].start, and when its processing is finished as
383+ // time[v].finish.
384+ let mut time: IndexVec < G :: Node , Time > =
385+ IndexVec :: from_elem_n ( Time :: default ( ) , graph. num_nodes ( ) ) ;
386+ let mut stack = Vec :: new ( ) ;
387+
388+ let mut discovered = 1 ;
389+ stack. push ( graph. start_node ( ) ) ;
390+ time[ graph. start_node ( ) ] . start = discovered;
391+
392+ while let Some ( & i) = stack. last ( ) {
393+ let e = & mut edges[ i] ;
394+ if e. start == e. end {
395+ // Finish processing vertex i.
396+ time[ i] . finish = discovered;
397+ stack. pop ( ) ;
398+ } else {
399+ let j = node[ e. start ] ;
400+ e. start += 1 ;
401+ // Start processing vertex j.
402+ discovered += 1 ;
403+ time[ j] . start = discovered;
404+ stack. push ( j) ;
405+ }
406+ }
407+
408+ Dominators { time, post_order_rank }
409+ }
0 commit comments