@@ -11,53 +11,59 @@ use std::cmp::Ordering;
11
11
#[ cfg( test) ]
12
12
mod tests;
13
13
14
- struct PreOrderFrame < Node , Iter > {
15
- node : Node ,
14
+ struct PreOrderFrame < Iter > {
15
+ pre_order_idx : PreorderIndex ,
16
16
iter : Iter ,
17
17
}
18
18
19
+ rustc_index:: newtype_index! {
20
+ struct PreorderIndex { .. }
21
+ }
22
+
19
23
pub fn dominators < G : ControlFlowGraph > ( graph : G ) -> Dominators < G :: Node > {
20
24
// compute the post order index (rank) for each node
21
25
let mut post_order_rank = IndexVec :: from_elem_n ( 0 , graph. num_nodes ( ) ) ;
22
- let mut parent: IndexVec < usize , Option < usize > > = IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
26
+ let mut parent: IndexVec < PreorderIndex , Option < PreorderIndex > > =
27
+ IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
23
28
24
- let mut stack = vec ! [ PreOrderFrame { node: 0 , iter: graph. successors( graph. start_node( ) ) } ] ;
25
- let mut pre_order_to_real = Vec :: with_capacity ( graph. num_nodes ( ) ) ;
26
- let mut real_to_pre_order: IndexVec < G :: Node , Option < usize > > =
29
+ let mut stack = vec ! [ PreOrderFrame {
30
+ pre_order_idx: PreorderIndex :: new( 0 ) ,
31
+ iter: graph. successors( graph. start_node( ) ) ,
32
+ } ] ;
33
+ let mut pre_order_to_real: IndexVec < PreorderIndex , G :: Node > =
34
+ IndexVec :: with_capacity ( graph. num_nodes ( ) ) ;
35
+ let mut real_to_pre_order: IndexVec < G :: Node , Option < PreorderIndex > > =
27
36
IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
28
37
pre_order_to_real. push ( graph. start_node ( ) ) ;
29
- real_to_pre_order[ graph. start_node ( ) ] = Some ( 0 ) ;
38
+ real_to_pre_order[ graph. start_node ( ) ] = Some ( PreorderIndex :: new ( 0 ) ) ;
30
39
let mut post_order_idx = 0 ;
31
40
32
41
' recurse: while let Some ( frame) = stack. last_mut ( ) {
33
42
while let Some ( successor) = frame. iter . next ( ) {
34
43
if real_to_pre_order[ successor] . is_none ( ) {
35
- let pre_order_idx = pre_order_to_real. len ( ) ;
36
-
44
+ let pre_order_idx = pre_order_to_real. push ( successor) ;
37
45
real_to_pre_order[ successor] = Some ( pre_order_idx) ;
38
- parent[ pre_order_idx] = Some ( frame. node ) ;
39
- pre_order_to_real. push ( successor) ;
40
- stack
41
- . push ( PreOrderFrame { node : pre_order_idx, iter : graph. successors ( successor) } ) ;
46
+ parent[ pre_order_idx] = Some ( frame. pre_order_idx ) ;
47
+ stack. push ( PreOrderFrame { pre_order_idx, iter : graph. successors ( successor) } ) ;
42
48
43
49
continue ' recurse;
44
50
}
45
51
}
46
- post_order_rank[ pre_order_to_real[ frame. node ] ] = post_order_idx;
52
+ post_order_rank[ pre_order_to_real[ frame. pre_order_idx ] ] = post_order_idx;
47
53
post_order_idx += 1 ;
48
54
49
55
stack. pop ( ) ;
50
56
}
51
57
52
58
let reachable_vertices = pre_order_to_real. len ( ) ;
53
59
54
- let mut idom = IndexVec :: from_elem_n ( 0 , reachable_vertices) ;
60
+ let mut idom = IndexVec :: from_elem_n ( PreorderIndex :: new ( 0 ) , reachable_vertices) ;
55
61
let mut semi = IndexVec :: from_fn_n ( std:: convert:: identity, reachable_vertices) ;
56
62
let mut label = semi. clone ( ) ;
57
63
let mut bucket = IndexVec :: from_elem_n ( vec ! [ ] , reachable_vertices) ;
58
64
let mut lastlinked = None ;
59
65
60
- for w in ( 1 .. reachable_vertices) . rev ( ) {
66
+ for w in ( PreorderIndex :: new ( 1 ) .. PreorderIndex :: new ( reachable_vertices) ) . rev ( ) {
61
67
// Optimization: process buckets just once, at the start of the
62
68
// iteration. Do not explicitly empty the bucket (even though it will
63
69
// not be used again), to save some instructions.
@@ -87,27 +93,28 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
87
93
// processed elements; lastlinked represents the divider.
88
94
lastlinked = Some ( w) ;
89
95
}
90
- for w in 1 .. reachable_vertices {
96
+ for w in PreorderIndex :: new ( 1 ) .. PreorderIndex :: new ( reachable_vertices) {
91
97
if idom[ w] != semi[ w] {
92
98
idom[ w] = idom[ idom[ w] ] ;
93
99
}
94
100
}
95
101
96
102
let mut immediate_dominators = IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
97
- for ( idx, node) in pre_order_to_real. iter ( ) . enumerate ( ) {
103
+ for ( idx, node) in pre_order_to_real. iter_enumerated ( ) {
98
104
immediate_dominators[ * node] = Some ( pre_order_to_real[ idom[ idx] ] ) ;
99
105
}
100
106
101
107
Dominators { post_order_rank, immediate_dominators }
102
108
}
103
109
104
- fn eval < N : Idx > (
105
- ancestor : & mut IndexVec < N , Option < N > > ,
106
- lastlinked : Option < N > ,
107
- semi : & IndexVec < N , N > ,
108
- label : & mut IndexVec < N , N > ,
109
- node : N ,
110
- ) -> N {
110
+ #[ inline]
111
+ fn eval (
112
+ ancestor : & mut IndexVec < PreorderIndex , Option < PreorderIndex > > ,
113
+ lastlinked : Option < PreorderIndex > ,
114
+ semi : & IndexVec < PreorderIndex , PreorderIndex > ,
115
+ label : & mut IndexVec < PreorderIndex , PreorderIndex > ,
116
+ node : PreorderIndex ,
117
+ ) -> PreorderIndex {
111
118
if is_processed ( node, lastlinked) {
112
119
compress ( ancestor, lastlinked, semi, label, node) ;
113
120
label[ node]
@@ -116,16 +123,18 @@ fn eval<N: Idx>(
116
123
}
117
124
}
118
125
119
- fn is_processed < N : Idx > ( v : N , lastlinked : Option < N > ) -> bool {
126
+ #[ inline]
127
+ fn is_processed ( v : PreorderIndex , lastlinked : Option < PreorderIndex > ) -> bool {
120
128
if let Some ( ll) = lastlinked { v >= ll } else { false }
121
129
}
122
130
123
- fn compress < N : Idx > (
124
- ancestor : & mut IndexVec < N , Option < N > > ,
125
- lastlinked : Option < N > ,
126
- semi : & IndexVec < N , N > ,
127
- label : & mut IndexVec < N , N > ,
128
- v : N ,
131
+ #[ inline]
132
+ fn compress (
133
+ ancestor : & mut IndexVec < PreorderIndex , Option < PreorderIndex > > ,
134
+ lastlinked : Option < PreorderIndex > ,
135
+ semi : & IndexVec < PreorderIndex , PreorderIndex > ,
136
+ label : & mut IndexVec < PreorderIndex , PreorderIndex > ,
137
+ v : PreorderIndex ,
129
138
) {
130
139
assert ! ( is_processed( v, lastlinked) ) ;
131
140
let u = ancestor[ v] . unwrap ( ) ;
0 commit comments