@@ -95,6 +95,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
9595
9696 let mut start = START_BLOCK ;
9797
98+ // Vec of the blocks that should be merged. We store the indices here, instead of the
99+ // statements itself to avoid moving the (relatively) large statements twice.
100+ // We do not push the statements directly into the target block (`bb`) as that is slower
101+ // due to additional reallocations
102+ let mut merged_blocks = Vec :: new ( ) ;
98103 loop {
99104 let mut changed = false ;
100105
@@ -114,18 +119,28 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
114119 self . collapse_goto_chain ( successor, & mut changed) ;
115120 }
116121
117- let mut new_stmts = vec ! [ ] ;
118122 let mut inner_changed = true ;
123+ merged_blocks. clear ( ) ;
119124 while inner_changed {
120125 inner_changed = false ;
121126 inner_changed |= self . simplify_branch ( & mut terminator) ;
122- inner_changed |= self . merge_successor ( & mut new_stmts , & mut terminator) ;
127+ inner_changed |= self . merge_successor ( & mut merged_blocks , & mut terminator) ;
123128 changed |= inner_changed;
124129 }
125130
126- let data = & mut self . basic_blocks [ bb] ;
127- data. statements . extend ( new_stmts) ;
128- data. terminator = Some ( terminator) ;
131+ let statements_to_merge =
132+ merged_blocks. iter ( ) . map ( |& i| self . basic_blocks [ i] . statements . len ( ) ) . sum ( ) ;
133+
134+ if statements_to_merge > 0 {
135+ let mut statements = std:: mem:: take ( & mut self . basic_blocks [ bb] . statements ) ;
136+ statements. reserve ( statements_to_merge) ;
137+ for & from in & merged_blocks {
138+ statements. append ( & mut self . basic_blocks [ from] . statements ) ;
139+ }
140+ self . basic_blocks [ bb] . statements = statements;
141+ }
142+
143+ self . basic_blocks [ bb] . terminator = Some ( terminator) ;
129144
130145 changed |= inner_changed;
131146 }
@@ -199,7 +214,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
199214 // merge a block with 1 `goto` predecessor to its parent
200215 fn merge_successor (
201216 & mut self ,
202- new_stmts : & mut Vec < Statement < ' tcx > > ,
217+ merged_blocks : & mut Vec < BasicBlock > ,
203218 terminator : & mut Terminator < ' tcx > ,
204219 ) -> bool {
205220 let target = match terminator. kind {
@@ -216,7 +231,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
216231 return false ;
217232 }
218233 } ;
219- new_stmts. extend ( self . basic_blocks [ target] . statements . drain ( ..) ) ;
234+
235+ merged_blocks. push ( target) ;
220236 self . pred_count [ target] = 0 ;
221237
222238 true
0 commit comments