about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2025-06-17 00:28:16 -0700
committerGitHub <noreply@github.com>2025-06-17 00:28:16 -0700
commit725d8291ab2b71984060ed08fc5a4d3d9ba75d6b (patch)
tree2a64de2a12fd0f4ead853329eec7832a5ad9fda2 /compiler
parenta2a767a5c7c9e6c7a4b2e5565b81b0758d7021de (diff)
parenta2d96875a58f0de8cad410a285fb8b4fa0dfa038 (diff)
downloadrust-725d8291ab2b71984060ed08fc5a4d3d9ba75d6b.tar.gz
rust-725d8291ab2b71984060ed08fc5a4d3d9ba75d6b.zip
Rollup merge of #142542 - cjgillot:invalidate-simplify-cfg, r=SparrowLii
Manually invalidate caches in SimplifyCfg.

The current `SimplifyCfg` pass unconditionally invalidates CFG caches. This is unfortunate if there are no modifications that require this invalidation.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs19
1 files changed, 16 insertions, 3 deletions
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 8f88228d9bb..a54e548ad70 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -74,7 +74,11 @@ impl SimplifyCfg {
 }
 
 pub(super) fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    CfgSimplifier::new(tcx, body).simplify();
+    if CfgSimplifier::new(tcx, body).simplify() {
+        // `simplify` returns that it changed something. We must invalidate the CFG caches as they
+        // are not consistent with the modified CFG any more.
+        body.basic_blocks.invalidate_cfg_cache();
+    }
     remove_dead_blocks(body);
 
     // FIXME: Should probably be moved into some kind of pass manager
@@ -121,12 +125,16 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
         // Preserve `SwitchInt` reads on built and analysis MIR, or if `-Zmir-preserve-ub`.
         let preserve_switch_reads = matches!(body.phase, MirPhase::Built | MirPhase::Analysis(_))
             || tcx.sess.opts.unstable_opts.mir_preserve_ub;
-        let basic_blocks = body.basic_blocks_mut();
+        // Do not clear caches yet. The caller to `simplify` will do it if anything changed.
+        let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
 
         CfgSimplifier { preserve_switch_reads, basic_blocks, pred_count }
     }
 
-    fn simplify(mut self) {
+    /// Returns whether we actually simplified anything. In that case, the caller *must* invalidate
+    /// the CFG caches of the MIR body.
+    #[must_use]
+    fn simplify(mut self) -> bool {
         self.strip_nops();
 
         // Vec of the blocks that should be merged. We store the indices here, instead of the
@@ -134,6 +142,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
         // We do not push the statements directly into the target block (`bb`) as that is slower
         // due to additional reallocations
         let mut merged_blocks = Vec::new();
+        let mut outer_changed = false;
         loop {
             let mut changed = false;
 
@@ -177,7 +186,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
             if !changed {
                 break;
             }
+
+            outer_changed = true;
         }
+
+        outer_changed
     }
 
     /// This function will return `None` if