@@ -74,7 +74,11 @@ 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+ // `simplify` returns that it changed something. We must invalidate the CFG caches as they
79+ // are not consistent with the modified CFG any more.
80+ body. basic_blocks . invalidate_cfg_cache ( ) ;
81+ }
7882 remove_dead_blocks ( body) ;
7983
8084 // FIXME: Should probably be moved into some kind of pass manager
@@ -121,19 +125,24 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
121125 // Preserve `SwitchInt` reads on built and analysis MIR, or if `-Zmir-preserve-ub`.
122126 let preserve_switch_reads = matches ! ( body. phase, MirPhase :: Built | MirPhase :: Analysis ( _) )
123127 || tcx. sess . opts . unstable_opts . mir_preserve_ub ;
124- let basic_blocks = body. basic_blocks_mut ( ) ;
128+ // Do not clear caches yet. The caller to `simplify` will do it if anything changed.
129+ let basic_blocks = body. basic_blocks . as_mut_preserves_cfg ( ) ;
125130
126131 CfgSimplifier { preserve_switch_reads, basic_blocks, pred_count }
127132 }
128133
129- fn simplify ( mut self ) {
134+ /// Returns whether we actually simplified anything. In that case, the caller *must* invalidate
135+ /// the CFG caches of the MIR body.
136+ #[ must_use]
137+ fn simplify ( mut self ) -> bool {
130138 self . strip_nops ( ) ;
131139
132140 // Vec of the blocks that should be merged. We store the indices here, instead of the
133141 // statements itself to avoid moving the (relatively) large statements twice.
134142 // We do not push the statements directly into the target block (`bb`) as that is slower
135143 // due to additional reallocations
136144 let mut merged_blocks = Vec :: new ( ) ;
145+ let mut outer_changed = false ;
137146 loop {
138147 let mut changed = false ;
139148
@@ -177,7 +186,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
177186 if !changed {
178187 break ;
179188 }
189+
190+ outer_changed = true ;
180191 }
192+
193+ outer_changed
181194 }
182195
183196 /// This function will return `None` if
0 commit comments