@@ -26,7 +26,42 @@ rustc_index::newtype_index! {
26
26
struct PreorderIndex { }
27
27
}
28
28
29
- pub fn dominators < G : ControlFlowGraph > ( graph : & G ) -> Dominators < G :: Node > {
29
+ #[ derive( Clone , Debug ) ]
30
+ pub struct Dominators < Node : Idx > {
31
+ kind : Kind < Node > ,
32
+ }
33
+
34
+ #[ derive( Clone , Debug ) ]
35
+ enum Kind < Node : Idx > {
36
+ /// A representation optimized for a small path graphs.
37
+ Path ( usize ) ,
38
+ General ( Inner < Node > ) ,
39
+ }
40
+
41
+ pub fn dominators < G : ControlFlowGraph > ( g : & G ) -> Dominators < G :: Node > {
42
+ // We often encounter MIR bodies with 1 or 2 basic blocks. Special case the dominators
43
+ // computation and representation for those cases.
44
+ if is_small_path_graph ( g) {
45
+ Dominators { kind : Kind :: Path ( g. num_nodes ( ) ) }
46
+ } else {
47
+ Dominators { kind : Kind :: General ( dominators_impl ( g) ) }
48
+ }
49
+ }
50
+
51
+ fn is_small_path_graph < G : ControlFlowGraph > ( g : & G ) -> bool {
52
+ if g. start_node ( ) . index ( ) != 0 {
53
+ return false ;
54
+ }
55
+ if g. num_nodes ( ) == 1 {
56
+ return true ;
57
+ }
58
+ if g. num_nodes ( ) == 2 {
59
+ return g. successors ( g. start_node ( ) ) . any ( |n| n. index ( ) == 1 ) ;
60
+ }
61
+ false
62
+ }
63
+
64
+ fn dominators_impl < G : ControlFlowGraph > ( graph : & G ) -> Inner < G :: Node > {
30
65
// compute the post order index (rank) for each node
31
66
let mut post_order_rank = IndexVec :: from_elem_n ( 0 , graph. num_nodes ( ) ) ;
32
67
@@ -245,7 +280,7 @@ pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
245
280
246
281
let time = compute_access_time ( start_node, & immediate_dominators) ;
247
282
248
- Dominators { post_order_rank, immediate_dominators, time }
283
+ Inner { post_order_rank, immediate_dominators, time }
249
284
}
250
285
251
286
/// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -310,7 +345,7 @@ fn compress(
310
345
311
346
/// Tracks the list of dominators for each node.
312
347
#[ derive( Clone , Debug ) ]
313
- pub struct Dominators < N : Idx > {
348
+ struct Inner < N : Idx > {
314
349
post_order_rank : IndexVec < N , usize > ,
315
350
// Even though we track only the immediate dominator of each node, it's
316
351
// possible to get its full list of dominators by looking up the dominator
@@ -322,12 +357,24 @@ pub struct Dominators<N: Idx> {
322
357
impl < Node : Idx > Dominators < Node > {
323
358
/// Returns true if node is reachable from the start node.
324
359
pub fn is_reachable ( & self , node : Node ) -> bool {
325
- self . time [ node] . start != 0
360
+ match & self . kind {
361
+ Kind :: Path ( _) => true ,
362
+ Kind :: General ( g) => g. time [ node] . start != 0 ,
363
+ }
326
364
}
327
365
328
366
/// Returns the immediate dominator of node, if any.
329
367
pub fn immediate_dominator ( & self , node : Node ) -> Option < Node > {
330
- self . immediate_dominators [ node]
368
+ match & self . kind {
369
+ Kind :: Path ( n) => {
370
+ if 0 < node. index ( ) && node. index ( ) < * n {
371
+ Some ( Node :: new ( node. index ( ) - 1 ) )
372
+ } else {
373
+ None
374
+ }
375
+ }
376
+ Kind :: General ( g) => g. immediate_dominators [ node] ,
377
+ }
331
378
}
332
379
333
380
/// Provides an iterator over each dominator up the CFG, for the given Node.
@@ -342,7 +389,10 @@ impl<Node: Idx> Dominators<Node> {
342
389
/// of two unrelated nodes will also be consistent, but otherwise the order has no
343
390
/// meaning.) This method cannot be used to determine if either Node dominates the other.
344
391
pub fn cmp_in_dominator_order ( & self , lhs : Node , rhs : Node ) -> Ordering {
345
- self . post_order_rank [ rhs] . cmp ( & self . post_order_rank [ lhs] )
392
+ match & self . kind {
393
+ Kind :: Path ( _) => lhs. index ( ) . cmp ( & rhs. index ( ) ) ,
394
+ Kind :: General ( g) => g. post_order_rank [ rhs] . cmp ( & g. post_order_rank [ lhs] ) ,
395
+ }
346
396
}
347
397
348
398
/// Returns true if `a` dominates `b`.
@@ -351,10 +401,15 @@ impl<Node: Idx> Dominators<Node> {
351
401
///
352
402
/// Panics if `b` is unreachable.
353
403
pub fn dominates ( & self , a : Node , b : Node ) -> bool {
354
- let a = self . time [ a] ;
355
- let b = self . time [ b] ;
356
- assert ! ( b. start != 0 , "node {b:?} is not reachable" ) ;
357
- a. start <= b. start && b. finish <= a. finish
404
+ match & self . kind {
405
+ Kind :: Path ( _) => a. index ( ) <= b. index ( ) ,
406
+ Kind :: General ( g) => {
407
+ let a = g. time [ a] ;
408
+ let b = g. time [ b] ;
409
+ assert ! ( b. start != 0 , "node {b:?} is not reachable" ) ;
410
+ a. start <= b. start && b. finish <= a. finish
411
+ }
412
+ }
358
413
}
359
414
}
360
415
0 commit comments