@@ -74,7 +74,9 @@ impl SimplifyCfg {
74
74
}
75
75
76
76
pub ( 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
+ }
78
80
remove_dead_blocks ( body) ;
79
81
80
82
// FIXME: Should probably be moved into some kind of pass manager
@@ -121,19 +123,23 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
121
123
// Preserve `SwitchInt` reads on built and analysis MIR, or if `-Zmir-preserve-ub`.
122
124
let preserve_switch_reads = matches ! ( body. phase, MirPhase :: Built | MirPhase :: Analysis ( _) )
123
125
|| 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 ( ) ;
125
127
126
128
CfgSimplifier { preserve_switch_reads, basic_blocks, pred_count }
127
129
}
128
130
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 {
130
135
self . strip_nops ( ) ;
131
136
132
137
// Vec of the blocks that should be merged. We store the indices here, instead of the
133
138
// statements itself to avoid moving the (relatively) large statements twice.
134
139
// We do not push the statements directly into the target block (`bb`) as that is slower
135
140
// due to additional reallocations
136
141
let mut merged_blocks = Vec :: new ( ) ;
142
+ let mut outer_changed = false ;
137
143
loop {
138
144
let mut changed = false ;
139
145
@@ -177,7 +183,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
177
183
if !changed {
178
184
break ;
179
185
}
186
+
187
+ outer_changed = true ;
180
188
}
189
+
190
+ outer_changed
181
191
}
182
192
183
193
/// This function will return `None` if
0 commit comments