8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ use rustc_data_structures:: bitvec:: BitVector ;
11
12
use rustc:: middle:: const_eval:: ConstVal ;
12
13
use rustc:: middle:: infer;
13
14
use rustc:: mir:: repr:: * ;
14
- use transform:: util;
15
15
use rustc:: mir:: transform:: MirPass ;
16
16
17
17
pub struct SimplifyCfg ;
@@ -22,23 +22,21 @@ impl SimplifyCfg {
22
22
}
23
23
24
24
fn remove_dead_blocks ( & self , mir : & mut Mir ) {
25
- let mut seen = vec ! [ false ; mir. basic_blocks. len( ) ] ;
26
-
25
+ let mut seen = BitVector :: new ( mir. basic_blocks . len ( ) ) ;
27
26
// These blocks are always required.
28
- seen[ START_BLOCK . index ( ) ] = true ;
29
- seen[ END_BLOCK . index ( ) ] = true ;
27
+ seen. insert ( START_BLOCK . index ( ) ) ;
28
+ seen. insert ( END_BLOCK . index ( ) ) ;
30
29
31
- let mut worklist = vec ! [ START_BLOCK ] ;
30
+ let mut worklist = Vec :: with_capacity ( 4 ) ;
31
+ worklist. push ( START_BLOCK ) ;
32
32
while let Some ( bb) = worklist. pop ( ) {
33
33
for succ in mir. basic_block_data ( bb) . terminator ( ) . successors ( ) . iter ( ) {
34
- if !seen[ succ. index ( ) ] {
35
- seen[ succ. index ( ) ] = true ;
34
+ if seen. insert ( succ. index ( ) ) {
36
35
worklist. push ( * succ) ;
37
36
}
38
37
}
39
38
}
40
-
41
- util:: retain_basic_blocks ( mir, & seen) ;
39
+ retain_basic_blocks ( mir, & seen) ;
42
40
}
43
41
44
42
fn remove_goto_chains ( & self , mir : & mut Mir ) -> bool {
@@ -90,12 +88,12 @@ impl SimplifyCfg {
90
88
for bb in mir. all_basic_blocks ( ) {
91
89
let basic_block = mir. basic_block_data_mut ( bb) ;
92
90
let mut terminator = basic_block. terminator_mut ( ) ;
93
-
94
91
* terminator = match * terminator {
95
92
Terminator :: If { ref targets, .. } if targets. 0 == targets. 1 => {
96
93
changed = true ;
97
94
Terminator :: Goto { target : targets. 0 }
98
95
}
96
+
99
97
Terminator :: If { ref targets, cond : Operand :: Constant ( Constant {
100
98
literal : Literal :: Value {
101
99
value : ConstVal :: Bool ( cond)
@@ -108,6 +106,7 @@ impl SimplifyCfg {
108
106
Terminator :: Goto { target : targets. 1 }
109
107
}
110
108
}
109
+
111
110
Terminator :: SwitchInt { ref targets, .. } if targets. len ( ) == 1 => {
112
111
Terminator :: Goto { target : targets[ 0 ] }
113
112
}
@@ -131,3 +130,27 @@ impl MirPass for SimplifyCfg {
131
130
mir. basic_blocks . shrink_to_fit ( ) ;
132
131
}
133
132
}
133
+
134
+ /// Mass removal of basic blocks to keep the ID-remapping cheap.
135
+ fn retain_basic_blocks ( mir : & mut Mir , keep : & BitVector ) {
136
+ let num_blocks = mir. basic_blocks . len ( ) ;
137
+
138
+ let mut replacements: Vec < _ > = ( 0 ..num_blocks) . map ( BasicBlock :: new) . collect ( ) ;
139
+ let mut used_blocks = 0 ;
140
+ for alive_index in keep. iter ( ) {
141
+ replacements[ alive_index] = BasicBlock :: new ( used_blocks) ;
142
+ if alive_index != used_blocks {
143
+ // Swap the next alive block data with the current available slot. Since alive_index is
144
+ // non-decreasing this is a valid operation.
145
+ mir. basic_blocks . swap ( alive_index, used_blocks) ;
146
+ }
147
+ used_blocks += 1 ;
148
+ }
149
+ mir. basic_blocks . truncate ( used_blocks) ;
150
+
151
+ for bb in mir. all_basic_blocks ( ) {
152
+ for target in mir. basic_block_data_mut ( bb) . terminator_mut ( ) . successors_mut ( ) {
153
+ * target = replacements[ target. index ( ) ] ;
154
+ }
155
+ }
156
+ }
0 commit comments