@@ -74,7 +74,9 @@ impl SimplifyCfg {
7474}
7575
7676pub ( super ) fn simplify_cfg < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
77- CfgSimplifier :: new ( tcx, body) . simplify ( ) ;
77+ if CfgSimplifier :: new ( tcx, body) . simplify ( ) {
78+ body. basic_blocks . invalidate_cfg_cache ( ) ;
79+ }
7880 remove_dead_blocks ( body) ;
7981
8082 // FIXME: Should probably be moved into some kind of pass manager
@@ -121,19 +123,23 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
121123 // Preserve `SwitchInt` reads on built and analysis MIR, or if `-Zmir-preserve-ub`.
122124 let preserve_switch_reads = matches ! ( body. phase, MirPhase :: Built | MirPhase :: Analysis ( _) )
123125 || tcx. sess . opts . unstable_opts . mir_preserve_ub ;
124- let basic_blocks = body. basic_blocks_mut ( ) ;
126+ let basic_blocks = body. basic_blocks . as_mut_preserves_cfg ( ) ;
125127
126128 CfgSimplifier { preserve_switch_reads, basic_blocks, pred_count }
127129 }
128130
129- fn simplify ( mut self ) {
131+ /// Returns whether we actually simplified anything. In that case, the caller *must* invalidate
132+ /// the CFG caches of the MIR body.
133+ #[ must_use]
134+ fn simplify ( mut self ) -> bool {
130135 self . strip_nops ( ) ;
131136
132137 // Vec of the blocks that should be merged. We store the indices here, instead of the
133138 // statements itself to avoid moving the (relatively) large statements twice.
134139 // We do not push the statements directly into the target block (`bb`) as that is slower
135140 // due to additional reallocations
136141 let mut merged_blocks = Vec :: new ( ) ;
142+ let mut outer_changed = false ;
137143 loop {
138144 let mut changed = false ;
139145
@@ -177,7 +183,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
177183 if !changed {
178184 break ;
179185 }
186+
187+ outer_changed = true ;
180188 }
189+
190+ outer_changed
181191 }
182192
183193 /// This function will return `None` if
0 commit comments