@@ -34,60 +34,53 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
34
34
}
35
35
36
36
let mut visited = BitSet :: new_empty ( graph. num_nodes ( ) ) ;
37
- let mut parent: IndexVec < G :: Node , Option < G :: Node > > =
38
- IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
39
- let mut pre_order_index: IndexVec < G :: Node , Option < usize > > =
40
- IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
41
- let mut pre_order_nodes = Vec :: with_capacity ( rpo. len ( ) ) ;
37
+ let mut parent: IndexVec < usize , Option < usize > > = IndexVec :: from_elem_n ( None , rpo. len ( ) ) ;
42
38
43
- let mut stack = vec ! [ PreOrderFrame {
44
- node: graph. start_node( ) ,
45
- iter: graph. successors( graph. start_node( ) ) ,
46
- } ] ;
39
+ let mut stack = vec ! [ PreOrderFrame { node: 0 , iter: graph. successors( graph. start_node( ) ) } ] ;
47
40
visited. insert ( graph. start_node ( ) ) ;
48
- let mut idx = 0 ;
49
- pre_order_index[ graph. start_node ( ) ] = Some ( 0 ) ;
50
- idx += 1 ;
51
- pre_order_nodes. push ( graph. start_node ( ) ) ;
41
+ let mut pre_order_to_real = Vec :: with_capacity ( rpo. len ( ) ) ;
42
+ let mut real_to_pre_order: IndexVec < G :: Node , Option < usize > > =
43
+ IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
44
+ pre_order_to_real. push ( graph. start_node ( ) ) ;
45
+ real_to_pre_order[ graph. start_node ( ) ] = Some ( 0 ) ;
46
+ let mut idx = 1 ;
52
47
53
48
' recurse: while let Some ( frame) = stack. last_mut ( ) {
54
49
while let Some ( successor) = frame. iter . next ( ) {
55
50
if visited. insert ( successor) {
56
- parent[ successor] = Some ( frame. node ) ;
57
- pre_order_index[ successor] = Some ( idx) ;
58
- pre_order_nodes. push ( successor) ;
59
- idx += 1 ;
51
+ parent[ idx] = Some ( frame. node ) ;
52
+ pre_order_to_real. push ( successor) ;
53
+ real_to_pre_order[ successor] = Some ( idx) ;
60
54
61
- stack. push ( PreOrderFrame { node : successor, iter : graph. successors ( successor) } ) ;
55
+ stack. push ( PreOrderFrame { node : idx, iter : graph. successors ( successor) } ) ;
56
+ idx += 1 ;
62
57
continue ' recurse;
63
58
}
64
59
}
65
60
stack. pop ( ) ;
66
61
}
67
62
68
- let mut idom = IndexVec :: from_elem_n ( graph . start_node ( ) , graph . num_nodes ( ) ) ;
69
- let mut semi = IndexVec :: from_fn_n ( std:: convert:: identity, graph . num_nodes ( ) ) ;
63
+ let mut idom = IndexVec :: from_elem_n ( 0 , pre_order_to_real . len ( ) ) ;
64
+ let mut semi = IndexVec :: from_fn_n ( std:: convert:: identity, pre_order_to_real . len ( ) ) ;
70
65
let mut label = semi. clone ( ) ;
71
- let mut bucket = IndexVec :: from_elem_n ( vec ! [ ] , graph . num_nodes ( ) ) ;
66
+ let mut bucket = IndexVec :: from_elem_n ( vec ! [ ] , pre_order_to_real . len ( ) ) ;
72
67
let mut lastlinked = None ;
73
68
74
- for & w in pre_order_nodes[ 1 ..] . iter ( ) . rev ( ) {
75
- // Optimization: process buckets just once. We need not explicitly empty
76
- // the bucket here, but mem::take is pretty cheap.
69
+ for w in ( 1 ..pre_order_to_real. len ( ) ) . rev ( ) {
70
+ // Optimization: process buckets just once, at the start of the
71
+ // iteration. Do not explicitly empty the bucket (even though it will
72
+ // not be used again), to save some instructions.
77
73
let z = parent[ w] . unwrap ( ) ;
78
- for v in std :: mem :: take ( & mut bucket[ z] ) {
79
- let y = eval ( & pre_order_index , & mut parent, lastlinked, & semi, & mut label, v) ;
80
- idom[ v] = if pre_order_index [ semi[ y] ] < pre_order_index [ z ] { y } else { z } ;
74
+ for & v in bucket[ z] . iter ( ) {
75
+ let y = eval ( & mut parent, lastlinked, & semi, & mut label, v) ;
76
+ idom[ v] = if semi[ y] < z { y } else { z } ;
81
77
}
82
78
83
79
semi[ w] = w;
84
- for v in graph. predecessors ( w) {
85
- let x = eval ( & pre_order_index, & mut parent, lastlinked, & semi, & mut label, v) ;
86
- semi[ w] = if pre_order_index[ semi[ w] ] . unwrap ( ) < pre_order_index[ semi[ x] ] . unwrap ( ) {
87
- semi[ w]
88
- } else {
89
- semi[ x]
90
- } ;
80
+ for v in graph. predecessors ( pre_order_to_real[ w] ) {
81
+ let v = real_to_pre_order[ v] . unwrap ( ) ;
82
+ let x = eval ( & mut parent, lastlinked, & semi, & mut label, v) ;
83
+ semi[ w] = std:: cmp:: min ( semi[ w] , semi[ x] ) ;
91
84
}
92
85
// semi[w] is now semidominator(w).
93
86
@@ -103,59 +96,51 @@ fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Domin
103
96
// processed elements; lastlinked represents the divider.
104
97
lastlinked = Some ( w) ;
105
98
}
106
- for & w in pre_order_nodes . iter ( ) . skip ( 1 ) {
99
+ for w in 1 ..pre_order_to_real . len ( ) {
107
100
if idom[ w] != semi[ w] {
108
101
idom[ w] = idom[ idom[ w] ] ;
109
102
}
110
103
}
111
104
112
105
let mut immediate_dominators = IndexVec :: from_elem_n ( None , graph. num_nodes ( ) ) ;
113
- for ( node, idom_slot) in immediate_dominators. iter_enumerated_mut ( ) {
114
- if pre_order_index[ node] . is_some ( ) {
115
- * idom_slot = Some ( idom[ node] ) ;
116
- }
106
+ for ( idx, node) in pre_order_to_real. iter ( ) . enumerate ( ) {
107
+ immediate_dominators[ * node] = Some ( pre_order_to_real[ idom[ idx] ] ) ;
117
108
}
118
109
119
110
Dominators { post_order_rank, immediate_dominators }
120
111
}
121
112
122
113
fn eval < N : Idx > (
123
- pre_order_index : & IndexVec < N , Option < usize > > ,
124
114
ancestor : & mut IndexVec < N , Option < N > > ,
125
115
lastlinked : Option < N > ,
126
116
semi : & IndexVec < N , N > ,
127
117
label : & mut IndexVec < N , N > ,
128
118
node : N ,
129
119
) -> N {
130
- if is_processed ( pre_order_index , node, lastlinked) {
131
- compress ( pre_order_index , ancestor, lastlinked, semi, label, node) ;
120
+ if is_processed ( node, lastlinked) {
121
+ compress ( ancestor, lastlinked, semi, label, node) ;
132
122
label[ node]
133
123
} else {
134
124
node
135
125
}
136
126
}
137
127
138
- fn is_processed < N : Idx > (
139
- pre_order_index : & IndexVec < N , Option < usize > > ,
140
- v : N ,
141
- lastlinked : Option < N > ,
142
- ) -> bool {
143
- if let Some ( ll) = lastlinked { pre_order_index[ v] >= pre_order_index[ ll] } else { false }
128
+ fn is_processed < N : Idx > ( v : N , lastlinked : Option < N > ) -> bool {
129
+ if let Some ( ll) = lastlinked { v >= ll } else { false }
144
130
}
145
131
146
132
fn compress < N : Idx > (
147
- pre_order_index : & IndexVec < N , Option < usize > > ,
148
133
ancestor : & mut IndexVec < N , Option < N > > ,
149
134
lastlinked : Option < N > ,
150
135
semi : & IndexVec < N , N > ,
151
136
label : & mut IndexVec < N , N > ,
152
137
v : N ,
153
138
) {
154
- assert ! ( is_processed( pre_order_index , v, lastlinked) ) ;
139
+ assert ! ( is_processed( v, lastlinked) ) ;
155
140
let u = ancestor[ v] . unwrap ( ) ;
156
- if is_processed ( pre_order_index , u, lastlinked) {
157
- compress ( pre_order_index , ancestor, lastlinked, semi, label, u) ;
158
- if pre_order_index [ semi[ label[ u] ] ] < pre_order_index [ semi[ label[ v] ] ] {
141
+ if is_processed ( u, lastlinked) {
142
+ compress ( ancestor, lastlinked, semi, label, u) ;
143
+ if semi[ label[ u] ] < semi[ label[ v] ] {
159
144
label[ v] = label[ u] ;
160
145
}
161
146
ancestor[ v] = ancestor[ u] ;
0 commit comments