about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform
diff options
context:
space:
mode:
authordianqk <dianqk@dianqk.net>2025-06-08 15:30:09 +0800
committerdianqk <dianqk@dianqk.net>2025-10-02 14:55:50 +0800
commit571412f8190089c36758031fe09fc0ece59be6b7 (patch)
tree3c1370be293a5aa1e4d8419ce9807b3f4b3b6ba1 /compiler/rustc_mir_transform
parent42b384ec0dfcd528d99a4db0a337d9188a9eecaa (diff)
downloadrust-571412f8190089c36758031fe09fc0ece59be6b7.tar.gz
rust-571412f8190089c36758031fe09fc0ece59be6b7.zip
mir-opt: Eliminate dead ref statements
Diffstat (limited to 'compiler/rustc_mir_transform')
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs4
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs55
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs2
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs2
-rw-r--r--compiler/rustc_mir_transform/src/patch.rs2
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/remove_place_mention.rs2
-rw-r--r--compiler/rustc_mir_transform/src/remove_storage_markers.rs2
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs29
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs4
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs10
16 files changed, 65 insertions, 63 deletions
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 4be67b873f7..b0bf7f484be 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -36,7 +36,9 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
                         CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. },
                     )
                     | StatementKind::FakeRead(..)
-                    | StatementKind::BackwardIncompatibleDropHint { .. } => statement.make_nop(),
+                    | StatementKind::BackwardIncompatibleDropHint { .. } => {
+                        statement.make_nop(true)
+                    }
                     StatementKind::Assign(box (
                         _,
                         Rvalue::Cast(
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index cddeefca681..f0bc286a940 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -138,7 +138,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
         if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = stmt.kind
             && self.storage_to_remove.contains(l)
         {
-            stmt.make_nop();
+            stmt.make_nop(true);
             return;
         }
 
@@ -150,7 +150,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
                 *rhs
             && lhs == rhs
         {
-            stmt.make_nop();
+            stmt.make_nop(true);
         }
     }
 }
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index c5cd06f170c..814eded910d 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -411,7 +411,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
             if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = s.kind
                 && self.remap.contains(l)
             {
-                s.make_nop();
+                s.make_nop(true);
             }
         }
 
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index eea2b0990d7..a5f8a22e83c 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -33,10 +33,9 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
     // If the user requests complete debuginfo, mark the locals that appear in it as live, so
     // we don't remove assignments to them.
-    let mut always_live = debuginfo_locals(body);
-    always_live.union(&borrowed_locals);
+    let debuginfo_locals = debuginfo_locals(body);
 
-    let mut live = MaybeTransitiveLiveLocals::new(&always_live)
+    let mut live = MaybeTransitiveLiveLocals::new(&borrowed_locals, &debuginfo_locals)
         .iterate_to_fixpoint(tcx, body, None)
         .into_results_cursor(body);
 
@@ -75,35 +74,23 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         }
 
         for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
-            let loc = Location { block: bb, statement_index };
-            if let StatementKind::Assign(assign) = &statement.kind {
-                if !assign.1.is_safe_to_remove() {
-                    continue;
-                }
-            }
-            match &statement.kind {
-                StatementKind::Assign(box (place, _))
-                | StatementKind::SetDiscriminant { place: box place, .. }
-                | StatementKind::Deinit(box place) => {
-                    if !place.is_indirect() && !always_live.contains(place.local) {
-                        live.seek_before_primary_effect(loc);
-                        if !live.get().contains(place.local) {
-                            patch.push(loc);
-                        }
-                    }
-                }
-                StatementKind::Retag(_, _)
-                | StatementKind::StorageLive(_)
-                | StatementKind::StorageDead(_)
-                | StatementKind::Coverage(_)
-                | StatementKind::Intrinsic(_)
-                | StatementKind::ConstEvalCounter
-                | StatementKind::PlaceMention(_)
-                | StatementKind::BackwardIncompatibleDropHint { .. }
-                | StatementKind::Nop => {}
-
-                StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
-                    bug!("{:?} not found in this MIR phase!", statement.kind)
+            if let Some(destination) = MaybeTransitiveLiveLocals::can_be_removed_if_dead(
+                &statement.kind,
+                &borrowed_locals,
+                &debuginfo_locals,
+            ) {
+                let loc = Location { block: bb, statement_index };
+                live.seek_before_primary_effect(loc);
+                if !live.get().contains(destination.local) {
+                    let drop_debuginfo = !debuginfo_locals.contains(destination.local);
+                    // When eliminating a dead statement, we need to address
+                    // the debug information for that statement.
+                    assert!(
+                        drop_debuginfo || statement.kind.as_debuginfo().is_some(),
+                        "don't know how to retain the debug information for {:?}",
+                        statement.kind
+                    );
+                    patch.push((loc, drop_debuginfo));
                 }
             }
         }
@@ -114,8 +101,8 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     }
 
     let bbs = body.basic_blocks.as_mut_preserves_cfg();
-    for Location { block, statement_index } in patch {
-        bbs[block].statements[statement_index].make_nop();
+    for (Location { block, statement_index }, drop_debuginfo) in patch {
+        bbs[block].statements[statement_index].make_nop(drop_debuginfo);
     }
     for (block, argument_index) in call_operands_to_move {
         let TerminatorKind::Call { ref mut args, .. } = bbs[block].terminator_mut().kind else {
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 74c22ff10c1..1f38433fa5a 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -276,7 +276,7 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
             StatementKind::StorageDead(local) | StatementKind::StorageLive(local)
                 if self.merged_locals.contains(*local) =>
             {
-                statement.make_nop();
+                statement.make_nop(true);
                 return;
             }
             _ => (),
@@ -291,7 +291,7 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
                         // (this includes the original statement we wanted to eliminate).
                         if dest == place {
                             debug!("{:?} turned into self-assignment, deleting", location);
-                            statement.make_nop();
+                            statement.make_nop(true);
                         }
                     }
                     _ => {}
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 99691d9e045..3ff8dc6dbb3 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1877,7 +1877,7 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> {
             StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
                 if self.reused_locals.contains(l) =>
             {
-                stmt.make_nop()
+                stmt.make_nop(true)
             }
             _ => self.super_statement(stmt, loc),
         }
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 1a91d6bd7da..1b90e9158f6 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -156,7 +156,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
                     patch.add_statement(location, stmt);
                 }
 
-                st.make_nop();
+                st.make_nop(true);
             }
         }
 
diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs
index cc8ea76011b..2c535d011a0 100644
--- a/compiler/rustc_mir_transform/src/patch.rs
+++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -270,7 +270,7 @@ impl<'tcx> MirPatch<'tcx> {
         body.local_decls.extend(self.new_locals);
 
         for loc in self.nop_statements {
-            bbs[loc.block].statements[loc.statement_index].make_nop();
+            bbs[loc.block].statements[loc.statement_index].make_nop(true);
         }
 
         let mut new_statements = self.new_statements;
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 48ddf5a1bca..c7dc18a4a13 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -1049,7 +1049,7 @@ fn promote_candidates<'tcx>(
     // Eliminate assignments to, and drops of promoted temps.
     let promoted = |index: Local| temps[index] == TempState::PromotedOut;
     for block in body.basic_blocks_mut() {
-        block.statements.retain(|statement| match &statement.kind {
+        block.retain_statements(|statement| match &statement.kind {
             StatementKind::Assign(box (place, _)) => {
                 if let Some(index) = place.as_local() {
                     !promoted(index)
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index b9d6e74ecae..deb0a146476 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -435,7 +435,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
             StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
                 if self.storage_to_remove.contains(l) =>
             {
-                stmt.make_nop();
+                stmt.make_nop(true);
             }
             // Do not remove assignments as they may still be useful for debuginfo.
             _ => self.super_statement(stmt, loc),
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
index cb598ceb4df..d56b51bb496 100644
--- a/compiler/rustc_mir_transform/src/remove_place_mention.rs
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -14,7 +14,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
     fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("Running RemovePlaceMention on {:?}", body.source);
         for data in body.basic_blocks.as_mut_preserves_cfg() {
-            data.statements.retain(|statement| match statement.kind {
+            data.retain_statements(|statement| match statement.kind {
                 StatementKind::PlaceMention(..) | StatementKind::Nop => false,
                 _ => true,
             })
diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
index 1ae33c00968..cb97d2c865a 100644
--- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs
+++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
@@ -14,7 +14,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers {
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("Running RemoveStorageMarkers on {:?}", body.source);
         for data in body.basic_blocks.as_mut_preserves_cfg() {
-            data.statements.retain(|statement| match statement.kind {
+            data.retain_statements(|statement| match statement.kind {
                 StatementKind::StorageLive(..)
                 | StatementKind::StorageDead(..)
                 | StatementKind::Nop => false,
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index c4dc8638b26..90c1b3520b9 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -141,7 +141,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
             && let ty = place_for_ty.ty(self.local_decls, self.tcx).ty
             && self.known_to_be_zst(ty)
         {
-            statement.make_nop();
+            statement.make_nop(true);
         } else {
             self.super_statement(statement, loc);
         }
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 75917d23883..9f7bb3b0379 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -36,7 +36,9 @@
 
 use itertools::Itertools as _;
 use rustc_index::{Idx, IndexSlice, IndexVec};
-use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::visit::{
+    MutVisitor, MutatingUseContext, NonUseContext, PlaceContext, Visitor,
+};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::DUMMY_SP;
@@ -303,7 +305,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
 
     fn strip_nops(&mut self) {
         for blk in self.basic_blocks.iter_mut() {
-            blk.statements.retain(|stmt| !matches!(stmt.kind, StatementKind::Nop))
+            blk.retain_statements(|stmt| !matches!(stmt.kind, StatementKind::Nop))
         }
     }
 }
@@ -539,12 +541,20 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
                 self.super_statement(statement, location);
             }
 
-            StatementKind::ConstEvalCounter | StatementKind::Nop => {}
-
-            StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {}
+            StatementKind::ConstEvalCounter
+            | StatementKind::Nop
+            | StatementKind::StorageLive(..)
+            | StatementKind::StorageDead(..) => {
+                for debuginfo in statement.debuginfos.iter() {
+                    self.visit_statement_debuginfo(debuginfo, location);
+                }
+            }
 
             StatementKind::Assign(box (ref place, ref rvalue)) => {
                 if rvalue.is_safe_to_remove() {
+                    for debuginfo in statement.debuginfos.iter() {
+                        self.visit_statement_debuginfo(debuginfo, location);
+                    }
                     self.visit_lhs(place, location);
                     self.visit_rvalue(rvalue, location);
                 } else {
@@ -555,15 +565,18 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
             StatementKind::SetDiscriminant { ref place, variant_index: _ }
             | StatementKind::Deinit(ref place)
             | StatementKind::BackwardIncompatibleDropHint { ref place, reason: _ } => {
+                for debuginfo in statement.debuginfos.iter() {
+                    self.visit_statement_debuginfo(debuginfo, location);
+                }
                 self.visit_lhs(place, location);
             }
         }
     }
 
-    fn visit_local(&mut self, local: Local, _ctx: PlaceContext, _location: Location) {
+    fn visit_local(&mut self, local: Local, ctx: PlaceContext, _location: Location) {
         if self.increment {
             self.use_count[local] += 1;
-        } else {
+        } else if ctx != PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
             assert_ne!(self.use_count[local], 0);
             self.use_count[local] -= 1;
         }
@@ -583,7 +596,7 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod
 
         for data in body.basic_blocks.as_mut_preserves_cfg() {
             // Remove unnecessary StorageLive and StorageDead annotations.
-            data.statements.retain(|statement| {
+            data.retain_statements(|statement| {
                 let keep = match &statement.kind {
                     StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
                         used_locals.is_used(*local)
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index c60eb566521..4597439e269 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -76,7 +76,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
             // delete comparison statement if it the value being switched on was moved, which means
             // it can not be user later on
             if opt.can_remove_bin_op_stmt {
-                bb.statements[opt.bin_op_stmt_idx].make_nop();
+                bb.statements[opt.bin_op_stmt_idx].make_nop(true);
             } else {
                 // if the integer being compared to a const integral is being moved into the
                 // comparison, e.g `_2 = Eq(move _3, const 'x');`
@@ -136,7 +136,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
         }
 
         for (idx, bb_idx) in storage_deads_to_remove {
-            body.basic_blocks_mut()[bb_idx].statements[idx].make_nop();
+            body.basic_blocks_mut()[bb_idx].statements[idx].make_nop(true);
         }
 
         for (idx, stmt) in storage_deads_to_insert {
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 38769885f36..99f10b8d91d 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -318,7 +318,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
                     for (_, _, fl) in final_locals {
                         self.patch.add_statement(location, StatementKind::StorageLive(fl));
                     }
-                    statement.make_nop();
+                    statement.make_nop(true);
                 }
                 return;
             }
@@ -327,7 +327,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
                     for (_, _, fl) in final_locals {
                         self.patch.add_statement(location, StatementKind::StorageDead(fl));
                     }
-                    statement.make_nop();
+                    statement.make_nop(true);
                 }
                 return;
             }
@@ -337,7 +337,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
                         self.patch
                             .add_statement(location, StatementKind::Deinit(Box::new(fl.into())));
                     }
-                    statement.make_nop();
+                    statement.make_nop(true);
                     return;
                 }
             }
@@ -367,7 +367,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
                             );
                         }
                     }
-                    statement.make_nop();
+                    statement.make_nop(true);
                     return;
                 }
             }
@@ -429,7 +429,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
                             StatementKind::Assign(Box::new((new_local.into(), rvalue))),
                         );
                     }
-                    statement.make_nop();
+                    statement.make_nop(true);
                     return;
                 }
             }