diff options
| author | dianqk <dianqk@dianqk.net> | 2025-07-19 18:49:47 +0800 |
|---|---|---|
| committer | dianqk <dianqk@dianqk.net> | 2025-10-02 14:58:59 +0800 |
| commit | 8da04285cf6fe61587e16155a8b224dba64bf0be (patch) | |
| tree | 4d4c98956c6bd938cd5ffe9bbfb7928a2f229a12 /compiler | |
| parent | 1bd89bd42e0bb6f29b8af5d6bdf3f756196bb8ee (diff) | |
| download | rust-8da04285cf6fe61587e16155a8b224dba64bf0be.tar.gz rust-8da04285cf6fe61587e16155a8b224dba64bf0be.zip | |
mir-opt: Eliminate dead statements even if they are used by debuginfos
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/statement.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/pretty.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/statement.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/visit.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/debuginfo.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_mir_dataflow/src/impls/liveness.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/simplify.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/strip_debuginfo.rs | 17 |
8 files changed, 66 insertions, 8 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 99bb31a68b6..80f4f0fcda1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -155,6 +155,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.debug_poison_to_local(bx, *dest); } } + StmtDebugInfo::InvalidAssign(local) => { + self.debug_poison_to_local(bx, *local); + } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 8cf89f778a2..d87e3abe3b2 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -844,6 +844,9 @@ impl Debug for StmtDebugInfo<'_> { StmtDebugInfo::AssignRef(local, place) => { write!(fmt, "{local:?} = &{place:?}") } + StmtDebugInfo::InvalidAssign(local) => { + write!(fmt, "{local:?} = &?") + } } } } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 67b4448cfcd..f310e1e5762 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -527,6 +527,20 @@ impl<'tcx> PlaceRef<'tcx> { }) } + /// Return the place accessed locals that include the base local. + pub fn accessed_locals(self) -> impl Iterator<Item = Local> { + std::iter::once(self.local).chain(self.projection.iter().filter_map(|proj| match proj { + ProjectionElem::Index(local) => Some(*local), + ProjectionElem::Deref + | ProjectionElem::Field(_, _) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Downcast(_, _) + | ProjectionElem::OpaqueCast(_) + | ProjectionElem::UnwrapUnsafeBinder(_) => None, + })) + } + /// Generates a new place by appending `more_projections` to the existing ones /// and interning the result. pub fn project_deeper( @@ -1057,4 +1071,5 @@ impl<'tcx> ops::DerefMut for StmtDebugInfos<'tcx> { #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum StmtDebugInfo<'tcx> { AssignRef(Local, Place<'tcx>), + InvalidAssign(Local), } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 47ae23afd55..9654e189f2e 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -406,6 +406,13 @@ macro_rules! make_mir_visitor { location ); }, + StmtDebugInfo::InvalidAssign(local) => { + self.visit_local( + $(& $mutability)? *local, + PlaceContext::NonUse(NonUseContext::VarDebugInfo), + location + ); + } } } diff --git a/compiler/rustc_mir_dataflow/src/debuginfo.rs b/compiler/rustc_mir_dataflow/src/debuginfo.rs index 274c5943946..0d25ce91c9a 100644 --- a/compiler/rustc_mir_dataflow/src/debuginfo.rs +++ b/compiler/rustc_mir_dataflow/src/debuginfo.rs @@ -5,16 +5,16 @@ use rustc_middle::mir::*; /// Return the set of locals that appear in debuginfo. pub fn debuginfo_locals(body: &Body<'_>) -> DenseBitSet<Local> { let mut visitor = DebuginfoLocals(DenseBitSet::new_empty(body.local_decls.len())); - visitor.visit_body(body); + for debuginfo in body.var_debug_info.iter() { + visitor.visit_var_debug_info(debuginfo); + } visitor.0 } struct DebuginfoLocals(DenseBitSet<Local>); impl Visitor<'_> for DebuginfoLocals { - fn visit_local(&mut self, local: Local, place_context: PlaceContext, _: Location) { - if place_context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) { - self.0.insert(local); - } + fn visit_local(&mut self, local: Local, _: PlaceContext, _: Location) { + self.0.insert(local); } } diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 037e2720f36..f6aaa65ad9f 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -287,9 +287,6 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { if let Some(destination) = Self::can_be_removed_if_dead(&statement.kind, &self.always_live, &self.debuginfo_locals) && !state.contains(destination.local) - // FIXME: We can eliminate the statement, but we'll need the statements it depends on - // for debuginfos. We need a way to handle this. - && !self.debuginfo_locals.contains(destination.local) { // This store is dead return; diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 0f23482ea8b..8b5efb74205 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -657,6 +657,22 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> { self.tcx } + fn visit_statement_debuginfo( + &mut self, + stmt_debuginfo: &mut StmtDebugInfo<'tcx>, + location: Location, + ) { + match stmt_debuginfo { + StmtDebugInfo::AssignRef(local, place) => { + if place.as_ref().accessed_locals().any(|local| self.map[local].is_none()) { + *stmt_debuginfo = StmtDebugInfo::InvalidAssign(*local); + } + } + StmtDebugInfo::InvalidAssign(_) => {} + } + self.super_statement_debuginfo(stmt_debuginfo, location); + } + fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { *l = self.map[*l].unwrap(); } diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs index 9ede8aa79c4..7fec25ccb52 100644 --- a/compiler/rustc_mir_transform/src/strip_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs @@ -1,5 +1,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::debuginfo::debuginfo_locals; use rustc_session::config::MirStripDebugInfo; /// Conditionally remove some of the VarDebugInfo in MIR. @@ -30,6 +31,22 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { if place.local.as_usize() <= body.arg_count && place.local != RETURN_PLACE, ) }); + + let debuginfo_locals = debuginfo_locals(body); + for data in body.basic_blocks.as_mut_preserves_cfg() { + for stmt in data.statements.iter_mut() { + stmt.debuginfos.retain(|debuginfo| match debuginfo { + StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { + debuginfo_locals.contains(*local) + } + }); + } + data.after_last_stmt_debuginfos.retain(|debuginfo| match debuginfo { + StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { + debuginfo_locals.contains(*local) + } + }); + } } fn is_required(&self) -> bool { |
