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