88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11+ use rustc_data_structures:: bitvec:: BitVector ;
1112use rustc:: middle:: const_eval:: ConstVal ;
1213use rustc:: middle:: infer;
1314use rustc:: mir:: repr:: * ;
14- use transform:: util;
1515use rustc:: mir:: transform:: MirPass ;
1616
1717pub struct SimplifyCfg ;
@@ -22,23 +22,21 @@ impl SimplifyCfg {
2222 }
2323
2424 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 ( ) ) ;
2726 // 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 ( ) ) ;
3029
31- let mut worklist = vec ! [ START_BLOCK ] ;
30+ let mut worklist = Vec :: with_capacity ( 4 ) ;
31+ worklist. push ( START_BLOCK ) ;
3232 while let Some ( bb) = worklist. pop ( ) {
3333 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 ( ) ) {
3635 worklist. push ( * succ) ;
3736 }
3837 }
3938 }
40-
41- util:: retain_basic_blocks ( mir, & seen) ;
39+ retain_basic_blocks ( mir, & seen) ;
4240 }
4341
4442 fn remove_goto_chains ( & self , mir : & mut Mir ) -> bool {
@@ -90,12 +88,12 @@ impl SimplifyCfg {
9088 for bb in mir. all_basic_blocks ( ) {
9189 let basic_block = mir. basic_block_data_mut ( bb) ;
9290 let mut terminator = basic_block. terminator_mut ( ) ;
93-
9491 * terminator = match * terminator {
9592 Terminator :: If { ref targets, .. } if targets. 0 == targets. 1 => {
9693 changed = true ;
9794 Terminator :: Goto { target : targets. 0 }
9895 }
96+
9997 Terminator :: If { ref targets, cond : Operand :: Constant ( Constant {
10098 literal : Literal :: Value {
10199 value : ConstVal :: Bool ( cond)
@@ -108,6 +106,7 @@ impl SimplifyCfg {
108106 Terminator :: Goto { target : targets. 1 }
109107 }
110108 }
109+
111110 Terminator :: SwitchInt { ref targets, .. } if targets. len ( ) == 1 => {
112111 Terminator :: Goto { target : targets[ 0 ] }
113112 }
@@ -131,3 +130,27 @@ impl MirPass for SimplifyCfg {
131130 mir. basic_blocks . shrink_to_fit ( ) ;
132131 }
133132}
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