From 51aa191df3680ef3d06d25569addf8740b61014e Mon Sep 17 00:00:00 2001 From: dianqk Date: Sun, 20 Apr 2025 22:09:29 +0800 Subject: [PATCH 1/4] mir: allow Nop to save a statement --- compiler/rustc_borrowck/src/dataflow.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 2 +- .../src/polonius/legacy/loan_invalidations.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_codegen_cranelift/src/base.rs | 2 +- .../rustc_codegen_cranelift/src/constant.rs | 2 +- .../rustc_codegen_ssa/src/mir/statement.rs | 8 +++-- .../src/check_consts/check.rs | 2 +- .../rustc_const_eval/src/interpret/step.rs | 35 ++++++++++--------- compiler/rustc_middle/src/mir/pretty.rs | 9 ++++- compiler/rustc_middle/src/mir/statement.rs | 12 +++++-- compiler/rustc_middle/src/mir/syntax.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 2 +- .../rustc_mir_dataflow/src/framework/tests.rs | 2 +- .../rustc_mir_dataflow/src/impls/liveness.rs | 2 +- .../src/impls/storage_liveness.rs | 2 +- .../src/move_paths/builder.rs | 2 +- .../src/cleanup_post_borrowck.rs | 4 ++- compiler/rustc_mir_transform/src/copy_prop.rs | 4 +-- compiler/rustc_mir_transform/src/coroutine.rs | 4 +-- .../src/coroutine/by_move_body.rs | 2 +- .../src/coverage/spans/from_mir.rs | 2 +- .../src/cross_crate_inline.rs | 2 +- .../src/dataflow_const_prop.rs | 2 +- .../src/dead_store_elimination.rs | 4 +-- compiler/rustc_mir_transform/src/dest_prop.rs | 6 ++-- compiler/rustc_mir_transform/src/gvn.rs | 2 +- .../rustc_mir_transform/src/jump_threading.rs | 2 +- .../rustc_mir_transform/src/large_enums.rs | 2 +- compiler/rustc_mir_transform/src/nrvo.rs | 6 ++-- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- .../src/remove_noop_landing_pads.rs | 2 +- .../src/remove_place_mention.rs | 3 +- .../src/remove_storage_markers.rs | 5 ++- .../rustc_mir_transform/src/remove_zsts.rs | 4 +-- compiler/rustc_mir_transform/src/simplify.rs | 6 ++-- .../src/simplify_branches.rs | 2 +- .../src/simplify_comparison_integral.rs | 4 +-- .../src/single_use_consts.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 10 +++--- compiler/rustc_mir_transform/src/validate.rs | 4 +-- .../rustc_smir/src/rustc_smir/convert/mir.rs | 2 +- 42 files changed, 100 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 7511a55b03ae5..f620888b51d81 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -626,7 +626,7 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { | mir::StatementKind::Intrinsic(..) | mir::StatementKind::ConstEvalCounter | mir::StatementKind::BackwardIncompatibleDropHint { .. } - | mir::StatementKind::Nop => {} + | mir::StatementKind::Nop(_) => {} } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3b66142eb2cec..b125203f428e8 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -770,7 +770,7 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt< state, ); } - StatementKind::Nop + StatementKind::Nop(_) | StatementKind::Retag { .. } | StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 0d1d8642bcacc..9fc04ac581f7e 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -82,7 +82,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { ); } StatementKind::ConstEvalCounter - | StatementKind::Nop + | StatementKind::Nop(_) | StatementKind::Retag { .. } | StatementKind::Deinit(..) | StatementKind::BackwardIncompatibleDropHint { .. } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3c00b819a96bb..a83a0c565469f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -731,7 +731,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..)) | StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => { diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index adaa754491e56..7f897d2c1f8ae 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -946,7 +946,7 @@ fn codegen_stmt<'tcx>( | StatementKind::StorageDead(_) | StatementKind::Deinit(_) | StatementKind::ConstEvalCounter - | StatementKind::Nop + | StatementKind::Nop(_) | StatementKind::FakeRead(..) | StatementKind::Retag { .. } | StatementKind::PlaceMention(..) diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index c8527c3a57dfe..d2343a07eaed9 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -591,7 +591,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | StatementKind::Coverage(_) | StatementKind::ConstEvalCounter | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} } } match &bb_data.terminator().kind { diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index cd55a838a7561..ebc088f7bcb89 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -92,8 +92,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::ConstEvalCounter | mir::StatementKind::PlaceMention(..) - | mir::StatementKind::BackwardIncompatibleDropHint { .. } - | mir::StatementKind::Nop => {} + | mir::StatementKind::BackwardIncompatibleDropHint { .. } => {} + mir::StatementKind::Nop(ref stmt) => { + if stmt.is_some() { + todo!("add debugging information") + } + } } } } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index b600b8918dd01..0bbc849219410 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -772,7 +772,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index ddf2d65914f6c..ca60896ea3b50 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -5,6 +5,7 @@ use either::Either; use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_index::IndexSlice; +use rustc_middle::mir::StatementKind; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, mir, span_bug}; @@ -77,51 +78,53 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn eval_statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> { info!("{:?}", stmt); - use rustc_middle::mir::StatementKind::*; - match &stmt.kind { - Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?, + StatementKind::Assign(box (place, rvalue)) => { + self.eval_rvalue_into_place(rvalue, *place)? + } - SetDiscriminant { place, variant_index } => { + StatementKind::SetDiscriminant { place, variant_index } => { let dest = self.eval_place(**place)?; self.write_discriminant(*variant_index, &dest)?; } - Deinit(place) => { + StatementKind::Deinit(place) => { let dest = self.eval_place(**place)?; self.write_uninit(&dest)?; } // Mark locals as alive - StorageLive(local) => { + StatementKind::StorageLive(local) => { self.storage_live(*local)?; } // Mark locals as dead - StorageDead(local) => { + StatementKind::StorageDead(local) => { self.storage_dead(*local)?; } // No dynamic semantics attached to `FakeRead`; MIR // interpreter is solely intended for borrowck'ed code. - FakeRead(..) => {} + StatementKind::FakeRead(..) => {} // Stacked Borrows. - Retag(kind, place) => { + StatementKind::Retag(kind, place) => { let dest = self.eval_place(**place)?; M::retag_place_contents(self, *kind, &dest)?; } - Intrinsic(box intrinsic) => self.eval_nondiverging_intrinsic(intrinsic)?, + StatementKind::Intrinsic(box intrinsic) => { + self.eval_nondiverging_intrinsic(intrinsic)? + } // Evaluate the place expression, without reading from it. - PlaceMention(box place) => { + StatementKind::PlaceMention(box place) => { let _ = self.eval_place(*place)?; } // This exists purely to guide borrowck lifetime inference, and does not have // an operational effect. - AscribeUserType(..) => {} + StatementKind::AscribeUserType(..) => {} // Currently, Miri discards Coverage statements. Coverage statements are only injected // via an optional compile time MIR pass and have no side effects. Since Coverage @@ -134,18 +137,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // following issue: // // FIXME(#73156): Handle source code coverage in const eval - Coverage(..) => {} + StatementKind::Coverage(..) => {} - ConstEvalCounter => { + StatementKind::ConstEvalCounter => { M::increment_const_eval_counter(self)?; } // Defined to do nothing. These are added by optimization passes, to avoid changing the // size of MIR constantly. - Nop => {} + StatementKind::Nop(_) => {} // Only used for temporary lifetime lints - BackwardIncompatibleDropHint { .. } => {} + StatementKind::BackwardIncompatibleDropHint { .. } => {} } interp_ok(()) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index d57019fee0f95..1f828a49425b1 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -855,7 +855,14 @@ impl Debug for Statement<'_> { Coverage(ref kind) => write!(fmt, "Coverage::{kind:?}"), Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), - Nop => write!(fmt, "nop"), + Nop(ref nop_stmt) => { + if let Some(box nop_stmt) = nop_stmt { + assert!(!matches!(nop_stmt, StatementKind::Nop(_))); + write!(fmt, "Nop({nop_stmt:?})") + } else { + write!(fmt, "nop") + } + } BackwardIncompatibleDropHint { ref place, reason: _ } => { // For now, we don't record the reason because there is only one use case, // which is to report breaking change in drop order by Edition 2024 diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index d59b6df44ed5d..7a8dffc4a6b51 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -19,8 +19,14 @@ pub struct Statement<'tcx> { impl Statement<'_> { /// Changes a statement to a nop. This is both faster than deleting instructions and avoids /// invalidating statement indices in `Location`s. - pub fn make_nop(&mut self) { - self.kind = StatementKind::Nop + pub fn make_nop(&mut self, save_stmt: bool) { + if matches!(self.kind, StatementKind::Nop(_)) { + return; + } + let replaced_stmt = std::mem::replace(&mut self.kind, StatementKind::Nop(None)); + if save_stmt { + self.kind = StatementKind::Nop(Some(Box::new(replaced_stmt))); + } } } @@ -41,7 +47,7 @@ impl<'tcx> StatementKind<'tcx> { StatementKind::Coverage(..) => "Coverage", StatementKind::Intrinsic(..) => "Intrinsic", StatementKind::ConstEvalCounter => "ConstEvalCounter", - StatementKind::Nop => "Nop", + StatementKind::Nop(..) => "Nop", StatementKind::BackwardIncompatibleDropHint { .. } => "BackwardIncompatibleDropHint", } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 304b3caa6e19f..d49bf0f9c0899 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -455,7 +455,7 @@ pub enum StatementKind<'tcx> { ConstEvalCounter, /// No-op. Useful for deleting instructions without affecting statement indices. - Nop, + Nop(Option>>), /// Marker statement indicating where `place` would be dropped. /// This is semantically equivalent to `Nop`, so codegen and MIRI should interpret this diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index de4d5140e8577..984923ef3c9a3 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -465,7 +465,7 @@ macro_rules! make_mir_visitor { ); } StatementKind::ConstEvalCounter => {} - StatementKind::Nop => {} + StatementKind::Nop(_) => {} } } diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index ae0f1179e6fac..9f925bb145508 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -17,7 +17,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { let mut blocks = IndexVec::new(); let mut block = |n, kind| { - let nop = mir::Statement { source_info, kind: mir::StatementKind::Nop }; + let nop = mir::Statement { source_info, kind: mir::StatementKind::Nop(None) }; blocks.push(mir::BasicBlockData { statements: std::iter::repeat(&nop).cloned().take(n).collect(), diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 6ec1b03a34e68..4ac2218eced01 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -254,7 +254,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => None, + | StatementKind::Nop(_) => None, }; if let Some(destination) = destination { if !destination.is_indirect() diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index e3aa8f5a62014..a5fc1fe9ebeb7 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -168,7 +168,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { | StatementKind::Coverage(..) | StatementKind::FakeRead(..) | StatementKind::ConstEvalCounter - | StatementKind::Nop + | StatementKind::Nop(..) | StatementKind::Retag(..) | StatementKind::Intrinsic(..) | StatementKind::BackwardIncompatibleDropHint { .. } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 8bbc89fdcecb7..e527377b3f807 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -388,7 +388,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} } } diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 4be67b873f737..a84e4be505644 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(false) + } 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 27af5818982d0..fedfa5df90000 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -156,7 +156,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(false); return; } @@ -168,7 +168,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { *rhs && lhs == rhs { - stmt.make_nop(); + stmt.make_nop(false); } } } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 92d5e152f58e6..cd3fe0cc16bb9 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -397,7 +397,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(false); } } @@ -1778,7 +1778,7 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> { | StatementKind::Intrinsic(..) | StatementKind::ConstEvalCounter | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} } } diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index dd0e07f2218eb..fea91a5e2330c 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -344,7 +344,7 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { } = place.as_ref() && let Some(&(_, _, true, _)) = self.field_remapping.get(&idx) { - statement.kind = mir::StatementKind::Nop; + statement.kind = mir::StatementKind::Nop(None); } self.super_statement(statement, location); diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 804cd8ab3f7d3..ed9063dd5c0ec 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -63,7 +63,7 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option { | StatementKind::StorageDead(_) | StatementKind::ConstEvalCounter | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => None, + | StatementKind::Nop(_) => None, // FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead` // statements be more consistent? diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 4f45d9588a890..4a4161ed6ce62 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -111,7 +111,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Deinit(_) - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} _ => self.statements += 1, } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 90173da17f0fc..bb08f0a1c3caf 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { // We don't track references. } StatementKind::ConstEvalCounter - | StatementKind::Nop + | StatementKind::Nop(_) | StatementKind::FakeRead(..) | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index eea2b0990d730..1fd1b341da0ad 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -100,7 +100,7 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(_) | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => { bug!("{:?} not found in this MIR phase!", statement.kind) @@ -115,7 +115,7 @@ 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(); + bbs[block].statements[statement_index].make_nop(false); } 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 7395ad496dbdf..c77634bdfcfd7 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -308,7 +308,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(false); return; } _ => (), @@ -323,7 +323,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(false); } } _ => {} @@ -595,7 +595,7 @@ impl WriteInfo { } StatementKind::Intrinsic(_) | StatementKind::ConstEvalCounter - | StatementKind::Nop + | StatementKind::Nop(_) | StatementKind::Coverage(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 8b8d1efbbd2e0..23fbfb84d2cd1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1840,7 +1840,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(false) } _ => self.super_statement(stmt, loc), } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 9732225e48ddd..e1e6946f88682 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -359,7 +359,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => None, + | StatementKind::Nop(_) => None, } } diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 47cb478fe33ee..4beeee803053d 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(false); } } diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 965002aae04c7..cc044c44e561d 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -54,7 +54,7 @@ impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace { // Clean up the `NOP`s we inserted for statements made useless by our renaming. for block_data in body.basic_blocks.as_mut_preserves_cfg() { - block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop); + block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop(None)); } // Overwrite the debuginfo of `_0` with that of the renamed local. @@ -170,7 +170,7 @@ impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { // return place: // _0 = _1 if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) { - stmt.kind = mir::StatementKind::Nop; + stmt.kind = mir::StatementKind::Nop(None); return; } @@ -180,7 +180,7 @@ impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { stmt.kind { if local == self.to_rename { - stmt.kind = mir::StatementKind::Nop; + stmt.kind = mir::StatementKind::Nop(None); return; } } diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 368d5340ac34f..ceb357df7d3ef 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -409,7 +409,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(false); } // 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_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 1dd34005d6641..ff83b69bc61b0 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -98,7 +98,7 @@ impl RemoveNoopLandingPads { | StatementKind::Coverage(..) | StatementKind::ConstEvalCounter | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => { + | StatementKind::Nop(_) => { // These are all noops in a landing pad } diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs index cb598ceb4dfea..1ebe62348db43 100644 --- a/compiler/rustc_mir_transform/src/remove_place_mention.rs +++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs @@ -15,7 +15,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention { trace!("Running RemovePlaceMention on {:?}", body.source); for data in body.basic_blocks.as_mut_preserves_cfg() { data.statements.retain(|statement| match statement.kind { - StatementKind::PlaceMention(..) | StatementKind::Nop => false, + StatementKind::PlaceMention(..) => false, + StatementKind::Nop(ref nop_stmt) => nop_stmt.is_some(), _ => true, }) } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index 1ae33c0096875..faa9004c48d3e 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -15,9 +15,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers { trace!("Running RemoveStorageMarkers on {:?}", body.source); for data in body.basic_blocks.as_mut_preserves_cfg() { data.statements.retain(|statement| match statement.kind { - StatementKind::StorageLive(..) - | StatementKind::StorageDead(..) - | StatementKind::Nop => false, + StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => false, + StatementKind::Nop(ref nop_stmt) => nop_stmt.is_some(), _ => true, }) } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 78d94a038671d..1f3d6d7b06e76 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -128,7 +128,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } StatementKind::Coverage(_) | StatementKind::Intrinsic(_) - | StatementKind::Nop + | StatementKind::Nop(_) | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::ConstEvalCounter => None, }; @@ -136,7 +136,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(false); } 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 4f2cce8ac1049..b68822d33dc5a 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -296,7 +296,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.statements.retain(|stmt| !matches!(stmt.kind, StatementKind::Nop(None))) } } } @@ -534,7 +534,7 @@ impl<'tcx> Visitor<'tcx> for UsedLocals { self.super_statement(statement, location); } - StatementKind::ConstEvalCounter | StatementKind::Nop => {} + StatementKind::ConstEvalCounter | StatementKind::Nop(_) => {} StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {} @@ -588,7 +588,7 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod StatementKind::SetDiscriminant { place, .. } | StatementKind::BackwardIncompatibleDropHint { place, reason: _ } | StatementKind::Deinit(place) => used_locals.is_used(place.local), - StatementKind::Nop => false, + StatementKind::Nop(nop_stmt) => nop_stmt.is_some(), _ => true, }; diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 886f4d6e50900..2a0303e2b6079 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -28,7 +28,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env) { if constant { - stmt.make_nop(); + stmt.make_nop(false); } else { block.statements.clear(); block.terminator_mut().kind = TerminatorKind::Unreachable; diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index bd00823073139..655972f7e20d4 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(false); } 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(false); } for (idx, stmt) in storage_deads_to_insert { diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 02caa92ad3fc8..99b2e364dbe02 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -50,7 +50,7 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); let init_statement_kind = std::mem::replace( &mut basic_blocks[init_loc.block].statements[init_loc.statement_index].kind, - StatementKind::Nop, + StatementKind::Nop(None), ); let StatementKind::Assign(place_and_rvalue) = init_statement_kind else { bug!("No longer an assign?"); diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 7c6ccc89c4f30..11a91a2d7ca7a 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -334,7 +334,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(false); } return; } @@ -343,7 +343,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(false); } return; } @@ -353,7 +353,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(false); return; } } @@ -383,7 +383,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { ); } } - statement.make_nop(); + statement.make_nop(false); return; } } @@ -445,7 +445,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { StatementKind::Assign(Box::new((new_local.into(), rvalue))), ); } - statement.make_nop(); + statement.make_nop(false); return; } } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 66fe3ef4141f5..13de2092739a4 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -342,7 +342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} } self.super_statement(statement, location); @@ -1534,7 +1534,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::Nop => {} + | StatementKind::Nop(_) => {} } self.super_statement(statement, location); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 61b769bce0831..12a5bd30180b5 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -156,7 +156,7 @@ impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> { mir::StatementKind::BackwardIncompatibleDropHint { .. } => { stable_mir::mir::StatementKind::Nop } - mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop, + mir::StatementKind::Nop(..) => stable_mir::mir::StatementKind::Nop, } } } From e2e0291d8472b9ea37376fe130a04624dbd5e987 Mon Sep 17 00:00:00 2001 From: dianqk Date: Thu, 17 Apr 2025 21:21:07 +0800 Subject: [PATCH 2/4] mir-opt: eliminate dead `Ref` assignments carrying debug information --- compiler/rustc_middle/src/mir/visit.rs | 23 +- .../rustc_mir_dataflow/src/impls/liveness.rs | 22 +- .../src/dead_store_elimination.rs | 49 +++-- compiler/rustc_mir_transform/src/simplify.rs | 17 +- ...y.run2-{closure#0}.Inline.panic-abort.diff | 40 ++-- ....run2-{closure#0}.Inline.panic-unwind.diff | 40 ++-- ...implifyComparisonIntegral.panic-abort.diff | 6 +- ...mplifyComparisonIntegral.panic-unwind.diff | 6 +- ...as_copy.clone_as_copy.PreCodegen.after.mir | 2 +- ...py.enum_clone_as_copy.PreCodegen.after.mir | 6 +- .../loops.filter_mapped.PreCodegen.after.mir | 44 ++-- .../loops.int_range.PreCodegen.after.mir | 90 ++++---- .../loops.mapped.PreCodegen.after.mir | 84 ++++---- ...variant_a-{closure#0}.PreCodegen.after.mir | 199 ++++++++---------- ...ans.outer.PreCodegen.after.panic-abort.mir | 2 +- ...ns.outer.PreCodegen.after.panic-unwind.mir | 2 +- 16 files changed, 338 insertions(+), 294 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 984923ef3c9a3..b003fdfeb4c89 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -465,7 +465,28 @@ macro_rules! make_mir_visitor { ); } StatementKind::ConstEvalCounter => {} - StatementKind::Nop(_) => {} + StatementKind::Nop(stmt) => { + if let Some(box stmt) = stmt { + match stmt { + StatementKind::Assign(box (place, rvalue)) => { + self.visit_place( + place, + PlaceContext::NonUse(NonUseContext::VarDebugInfo), + location + ); + match rvalue { + Rvalue::Ref(_, _, path) => { + self.visit_place(path, PlaceContext::NonUse(NonUseContext::VarDebugInfo), location); + } + _ => unimplemented!() + } + }, + _ => { + unimplemented!() + } + } + } + } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 4ac2218eced01..c5949fdd2c0ab 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -1,7 +1,7 @@ use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{ - self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges, + self, CallReturnPlaces, Local, Location, Place, Rvalue, StatementKind, TerminatorEdges, }; use crate::{Analysis, Backward, GenKill}; @@ -205,6 +205,7 @@ impl DefUse { /// All of the caveats of `MaybeLiveLocals` apply. pub struct MaybeTransitiveLiveLocals<'a> { always_live: &'a DenseBitSet, + debuginfo_locals: &'a DenseBitSet, } impl<'a> MaybeTransitiveLiveLocals<'a> { @@ -212,8 +213,11 @@ impl<'a> MaybeTransitiveLiveLocals<'a> { /// considered live. /// /// This should include at least all locals that are ever borrowed. - pub fn new(always_live: &'a DenseBitSet) -> Self { - MaybeTransitiveLiveLocals { always_live } + pub fn new( + always_live: &'a DenseBitSet, + debuginfo_locals: &'a DenseBitSet, + ) -> Self { + MaybeTransitiveLiveLocals { always_live, debuginfo_locals } } } @@ -240,9 +244,17 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { ) { // Compute the place that we are storing to, if any let destination = match &statement.kind { - StatementKind::Assign(assign) => assign.1.is_safe_to_remove().then_some(assign.0), + StatementKind::Assign(box (place, rvalue)) => { + if !self.debuginfo_locals.contains(place.local) + || (place.as_local().is_some() && matches!(rvalue, Rvalue::Ref(..))) + { + rvalue.is_safe_to_remove().then_some(*place) + } else { + None + } + } StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => { - Some(**place) + if self.debuginfo_locals.contains(place.local) { None } else { Some(**place) } } StatementKind::FakeRead(_) | StatementKind::StorageLive(_) diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 1fd1b341da0ad..852992f4f23a2 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); @@ -76,16 +75,26 @@ 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::Assign(box (place, rvalue)) => { + if rvalue.is_safe_to_remove() + && !place.is_indirect() + && !borrowed_locals.contains(place.local) + && (!debuginfo_locals.contains(place.local) + || (place.as_local().is_some() && matches!(rvalue, Rvalue::Ref(..)))) + { + live.seek_before_primary_effect(loc); + if !live.get().contains(place.local) { + patch.push(loc); + } + } + } + StatementKind::SetDiscriminant { place: box place, .. } | StatementKind::Deinit(box place) => { - if !place.is_indirect() && !always_live.contains(place.local) { + if !place.is_indirect() + && !borrowed_locals.contains(place.local) + && !debuginfo_locals.contains(place.local) + { live.seek_before_primary_effect(loc); if !live.get().contains(place.local) { patch.push(loc); @@ -115,7 +124,23 @@ 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(false); + let save_stmt = match bbs[block].statements[statement_index].kind { + StatementKind::Assign(box (place, _)) => debuginfo_locals.contains(place.local), + StatementKind::SetDiscriminant { .. } + | StatementKind::Deinit(_) + | StatementKind::Retag(_, _) + | StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::Coverage(_) + | StatementKind::Intrinsic(_) + | StatementKind::ConstEvalCounter + | StatementKind::PlaceMention(_) + | StatementKind::BackwardIncompatibleDropHint { .. } + | StatementKind::FakeRead(_) + | StatementKind::AscribeUserType(_, _) + | StatementKind::Nop(_) => false, + }; + bbs[block].statements[statement_index].make_nop(save_stmt); } 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/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index b68822d33dc5a..97a6e5dd630b3 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -533,7 +533,10 @@ impl<'tcx> Visitor<'tcx> for UsedLocals { | StatementKind::AscribeUserType(..) => { self.super_statement(statement, location); } - + StatementKind::Nop(Some(box StatementKind::Assign(box (ref place, ref rvalue)))) => { + self.visit_lhs(place, location); + self.visit_rvalue(rvalue, location); + } StatementKind::ConstEvalCounter | StatementKind::Nop(_) => {} StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {} @@ -588,7 +591,17 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod StatementKind::SetDiscriminant { place, .. } | StatementKind::BackwardIncompatibleDropHint { place, reason: _ } | StatementKind::Deinit(place) => used_locals.is_used(place.local), - StatementKind::Nop(nop_stmt) => nop_stmt.is_some(), + StatementKind::Nop(stmt) => { + if let Some(box stmt) = stmt { + if let Some((place, _)) = stmt.as_assign() { + used_locals.is_used(place.local) + } else { + unimplemented!() + } + } else { + false + } + } _ => true, }; diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 1e9a6dd4f5c8f..bbfa1b75c9625 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -64,9 +64,8 @@ + let mut _45: &mut std::future::Ready<()>; + let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 14 (inlined > as DerefMut>::deref_mut) { -+ let mut _47: std::pin::Pin<&mut std::future::Ready<()>>; + scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { -+ let mut _48: &mut &mut std::future::Ready<()>; ++ let mut _47: &mut &mut std::future::Ready<()>; + scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } + scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { @@ -76,15 +75,15 @@ + } + } + scope 19 (inlined Option::<()>::take) { -+ let mut _49: std::option::Option<()>; ++ let mut _48: std::option::Option<()>; + scope 20 (inlined std::mem::replace::>) { + scope 21 { + } + } + } + scope 22 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _50: isize; -+ let mut _51: !; ++ let mut _49: isize; ++ let mut _50: !; + scope 23 { + } + } @@ -229,28 +228,25 @@ + StorageDead(_24); + StorageLive(_45); + StorageLive(_46); -+ StorageLive(_51); ++ StorageLive(_50); + StorageLive(_42); + StorageLive(_43); + StorageLive(_44); -+ _46 = &mut _19; ++ Nop(Assign((_46, &mut _19))); + StorageLive(_47); -+ StorageLive(_48); -+ _48 = &mut (_19.0: &mut std::future::Ready<()>); ++ Nop(Assign((_47, &mut (_19.0: &mut std::future::Ready<()>)))); + _45 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_48); -+ _47 = Pin::<&mut std::future::Ready<()>> { pointer: copy _45 }; + StorageDead(_47); -+ _44 = &mut ((*_45).0: std::option::Option<()>); -+ StorageLive(_49); -+ _49 = Option::<()>::None; ++ Nop(Assign((_44, &mut ((*_45).0: std::option::Option<()>)))); ++ StorageLive(_48); ++ _48 = Option::<()>::None; + _43 = copy ((*_45).0: std::option::Option<()>); -+ ((*_45).0: std::option::Option<()>) = copy _49; -+ StorageDead(_49); ++ ((*_45).0: std::option::Option<()>) = copy _48; ++ StorageDead(_48); + StorageDead(_44); -+ StorageLive(_50); -+ _50 = discriminant(_43); -+ switchInt(move _50) -> [0: bb11, 1: bb12, otherwise: bb5]; ++ StorageLive(_49); ++ _49 = discriminant(_43); ++ switchInt(move _49) -> [0: bb11, 1: bb12, otherwise: bb5]; + } + + bb5: { @@ -313,16 +309,16 @@ + } + + bb11: { -+ _51 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; ++ _50 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; + } + + bb12: { + _42 = move ((_43 as Some).0: ()); -+ StorageDead(_50); ++ StorageDead(_49); + StorageDead(_43); + _18 = Poll::<()>::Ready(move _42); + StorageDead(_42); -+ StorageDead(_51); ++ StorageDead(_50); + StorageDead(_46); + StorageDead(_45); + StorageDead(_22); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 94b89a310baa8..19dd6762aed2f 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -66,9 +66,8 @@ + let mut _47: &mut std::future::Ready<()>; + let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 14 (inlined > as DerefMut>::deref_mut) { -+ let mut _49: std::pin::Pin<&mut std::future::Ready<()>>; + scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { -+ let mut _50: &mut &mut std::future::Ready<()>; ++ let mut _49: &mut &mut std::future::Ready<()>; + scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } + scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { @@ -78,15 +77,15 @@ + } + } + scope 19 (inlined Option::<()>::take) { -+ let mut _51: std::option::Option<()>; ++ let mut _50: std::option::Option<()>; + scope 20 (inlined std::mem::replace::>) { + scope 21 { + } + } + } + scope 22 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _52: isize; -+ let mut _53: !; ++ let mut _51: isize; ++ let mut _52: !; + scope 23 { + } + } @@ -246,28 +245,25 @@ + StorageDead(_24); + StorageLive(_47); + StorageLive(_48); -+ StorageLive(_53); ++ StorageLive(_52); + StorageLive(_44); + StorageLive(_45); + StorageLive(_46); -+ _48 = &mut _19; ++ Nop(Assign((_48, &mut _19))); + StorageLive(_49); -+ StorageLive(_50); -+ _50 = &mut (_19.0: &mut std::future::Ready<()>); ++ Nop(Assign((_49, &mut (_19.0: &mut std::future::Ready<()>)))); + _47 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_50); -+ _49 = Pin::<&mut std::future::Ready<()>> { pointer: copy _47 }; + StorageDead(_49); -+ _46 = &mut ((*_47).0: std::option::Option<()>); -+ StorageLive(_51); -+ _51 = Option::<()>::None; ++ Nop(Assign((_46, &mut ((*_47).0: std::option::Option<()>)))); ++ StorageLive(_50); ++ _50 = Option::<()>::None; + _45 = copy ((*_47).0: std::option::Option<()>); -+ ((*_47).0: std::option::Option<()>) = copy _51; -+ StorageDead(_51); ++ ((*_47).0: std::option::Option<()>) = copy _50; ++ StorageDead(_50); + StorageDead(_46); -+ StorageLive(_52); -+ _52 = discriminant(_45); -+ switchInt(move _52) -> [0: bb16, 1: bb17, otherwise: bb7]; ++ StorageLive(_51); ++ _51 = discriminant(_45); ++ switchInt(move _51) -> [0: bb16, 1: bb17, otherwise: bb7]; } - bb6 (cleanup): { @@ -354,16 +350,16 @@ + } + + bb16: { -+ _53 = option::expect_failed(const "`Ready` polled after completion") -> bb11; ++ _52 = option::expect_failed(const "`Ready` polled after completion") -> bb11; + } + + bb17: { + _44 = move ((_45 as Some).0: ()); -+ StorageDead(_52); ++ StorageDead(_51); + StorageDead(_45); + _18 = Poll::<()>::Ready(move _44); + StorageDead(_44); -+ StorageDead(_53); ++ StorageDead(_52); + StorageDead(_48); + StorageDead(_47); + StorageDead(_22); diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index c02bab3524bca..88f064291b799 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -38,11 +38,11 @@ bb2: { StorageLive(_7); - _7 = &(*_2)[0 of 3]; + Nop(Assign((_7, &(*_2)[0 of 3]))); StorageLive(_8); - _8 = &(*_2)[1 of 3]; + Nop(Assign((_8, &(*_2)[1 of 3]))); StorageLive(_9); - _9 = &(*_2)[2 of 3]; + Nop(Assign((_9, &(*_2)[2 of 3]))); StorageDead(_9); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index 49be042588cb3..b2e32f88e4ca8 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -38,11 +38,11 @@ bb2: { StorageLive(_7); - _7 = &(*_2)[0 of 3]; + Nop(Assign((_7, &(*_2)[0 of 3]))); StorageLive(_8); - _8 = &(*_2)[1 of 3]; + Nop(Assign((_8, &(*_2)[1 of 3]))); StorageLive(_9); - _9 = &(*_2)[2 of 3]; + Nop(Assign((_9, &(*_2)[2 of 3]))); StorageDead(_9); StorageDead(_8); StorageDead(_7); diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir index 34747e5a92854..186d0f6c361da 100644 --- a/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir @@ -13,7 +13,7 @@ fn clone_as_copy(_1: &NestCopy) -> NestCopy { bb0: { StorageLive(_2); - _2 = &((*_1).1: AllCopy); + Nop(Assign((_2, &((*_1).1: AllCopy)))); _0 = copy (*_1); StorageDead(_2); return; diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir index 9f88e1961ec88..c1fb6bf592b6f 100644 --- a/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir @@ -35,15 +35,15 @@ fn enum_clone_as_copy(_1: &Enum1) -> Enum1 { } bb1: { - _3 = &(((*_1) as A).0: AllCopy); + Nop(Assign((_3, &(((*_1) as A).0: AllCopy)))); _0 = copy (*_1); goto -> bb3; } bb2: { - _4 = &(((*_1) as B).0: NestCopy); + Nop(Assign((_4, &(((*_1) as B).0: NestCopy)))); StorageLive(_5); - _5 = &((((*_1) as B).0: NestCopy).1: AllCopy); + Nop(Assign((_5, &((((*_1) as B).0: NestCopy).1: AllCopy)))); StorageDead(_5); _0 = copy (*_1); goto -> bb3; diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 75e8cb1d8618c..cfdde43c406e4 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -6,20 +6,20 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () let mut _0: (); let mut _3: std::iter::FilterMap, impl Fn(T) -> Option>; let mut _4: std::iter::FilterMap, impl Fn(T) -> Option>; - let mut _5: &mut std::iter::FilterMap, impl Fn(T) -> Option>; - let mut _8: std::option::Option; - let mut _9: isize; - let _11: (); + let mut _7: std::option::Option; + let mut _8: isize; + let _10: (); + let mut _11: &mut std::iter::FilterMap, impl Fn(T) -> Option>; scope 1 { debug iter => _4; - let _10: U; + let _9: U; scope 2 { - debug x => _10; + debug x => _9; } scope 4 (inlined , impl Fn(T) -> Option> as Iterator>::next) { - debug self => _5; - let mut _6: &mut impl Iterator; - let mut _7: &mut impl Fn(T) -> Option; + debug self => _11; + let mut _5: &mut impl Iterator; + let mut _6: &mut impl Fn(T) -> Option; } } scope 3 (inlined , impl Fn(T) -> Option> as IntoIterator>::into_iter) { @@ -37,24 +37,24 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () } bb2: { - StorageLive(_8); - _5 = &mut _4; - StorageLive(_6); - _6 = &mut (_4.0: impl Iterator); StorageLive(_7); - _7 = &mut (_4.1: impl Fn(T) -> Option); - _8 = as Iterator>::find_map:: Option>(move _6, move _7) -> [return: bb3, unwind: bb9]; + Nop(Assign((_11, &mut _4))); + StorageLive(_5); + _5 = &mut (_4.0: impl Iterator); + StorageLive(_6); + _6 = &mut (_4.1: impl Fn(T) -> Option); + _7 = as Iterator>::find_map:: Option>(move _5, move _6) -> [return: bb3, unwind: bb9]; } bb3: { - StorageDead(_7); StorageDead(_6); - _9 = discriminant(_8); - switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb8]; + StorageDead(_5); + _8 = discriminant(_7); + switchInt(move _8) -> [0: bb4, 1: bb6, otherwise: bb8]; } bb4: { - StorageDead(_8); + StorageDead(_7); drop(_4) -> [return: bb5, unwind continue]; } @@ -64,12 +64,12 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () } bb6: { - _10 = move ((_8 as Some).0: U); - _11 = opaque::(move _10) -> [return: bb7, unwind: bb9]; + _9 = move ((_7 as Some).0: U); + _10 = opaque::(move _9) -> [return: bb7, unwind: bb9]; } bb7: { - StorageDead(_8); + StorageDead(_7); goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 1f9c464d633b3..5b9cb02dbcb7f 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -6,31 +6,31 @@ fn int_range(_1: usize, _2: usize) -> () { let mut _0: (); let mut _3: std::ops::Range; let mut _4: std::ops::Range; - let mut _5: &mut std::ops::Range; - let mut _13: std::option::Option; - let _15: (); + let mut _10: std::option::Option; + let _12: (); + let mut _13: &mut std::ops::Range; scope 1 { debug iter => _4; - let _14: usize; + let _11: usize; scope 2 { - debug i => _14; + debug i => _11; } scope 4 (inlined iter::range::>::next) { - debug self => _5; + debug self => _13; scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _5; - let mut _6: &usize; - let mut _7: &usize; - let mut _10: bool; - let _11: usize; - let mut _12: usize; + debug self => _13; + let mut _7: bool; + let _8: usize; + let mut _9: usize; + let mut _14: &usize; + let mut _15: &usize; scope 6 { - debug old => _11; + debug old => _8; scope 8 (inlined ::forward_unchecked) { - debug start => _11; + debug start => _8; debug n => const 1_usize; scope 9 (inlined core::num::::unchecked_add) { - debug self => _11; + debug self => _8; debug rhs => const 1_usize; scope 10 (inlined core::ub_checks::check_language_ub) { scope 11 (inlined core::ub_checks::check_language_ub::runtime) { @@ -40,10 +40,10 @@ fn int_range(_1: usize, _2: usize) -> () { } } scope 7 (inlined std::cmp::impls::::lt) { - debug self => _6; - debug other => _7; - let mut _8: usize; - let mut _9: usize; + debug self => _14; + debug other => _15; + let mut _5: usize; + let mut _6: usize; } } } @@ -60,48 +60,48 @@ fn int_range(_1: usize, _2: usize) -> () { } bb1: { - StorageLive(_13); - _5 = &mut _4; StorageLive(_10); - StorageLive(_6); - _6 = &(_4.0: usize); + Nop(Assign((_13, &mut _4))); StorageLive(_7); - _7 = &(_4.1: usize); - StorageLive(_8); - _8 = copy (_4.0: usize); - StorageLive(_9); - _9 = copy (_4.1: usize); - _10 = Lt(move _8, move _9); - StorageDead(_9); - StorageDead(_8); - switchInt(move _10) -> [0: bb2, otherwise: bb3]; + StorageLive(_14); + Nop(Assign((_14, &(_4.0: usize)))); + StorageLive(_15); + Nop(Assign((_15, &(_4.1: usize)))); + StorageLive(_5); + _5 = copy (_4.0: usize); + StorageLive(_6); + _6 = copy (_4.1: usize); + _7 = Lt(move _5, move _6); + StorageDead(_6); + StorageDead(_5); + switchInt(move _7) -> [0: bb2, otherwise: bb3]; } bb2: { + StorageDead(_15); + StorageDead(_14); StorageDead(_7); - StorageDead(_6); StorageDead(_10); - StorageDead(_13); StorageDead(_4); return; } bb3: { + StorageDead(_15); + StorageDead(_14); + _8 = copy (_4.0: usize); + StorageLive(_9); + _9 = AddUnchecked(copy _8, const 1_usize); + (_4.0: usize) = move _9; + StorageDead(_9); + _10 = Option::::Some(copy _8); StorageDead(_7); - StorageDead(_6); - _11 = copy (_4.0: usize); - StorageLive(_12); - _12 = AddUnchecked(copy _11, const 1_usize); - (_4.0: usize) = move _12; - StorageDead(_12); - _13 = Option::::Some(copy _11); - StorageDead(_10); - _14 = copy ((_13 as Some).0: usize); - _15 = opaque::(move _14) -> [return: bb4, unwind continue]; + _11 = copy ((_10 as Some).0: usize); + _12 = opaque::(move _11) -> [return: bb4, unwind continue]; } bb4: { - StorageDead(_13); + StorageDead(_10); goto -> bb1; } } diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index d22ea54004c91..2a7005b01b8f4 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -6,32 +6,32 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { let mut _0: (); let mut _3: std::iter::Map, impl Fn(T) -> U>; let mut _4: std::iter::Map, impl Fn(T) -> U>; - let mut _5: &mut std::iter::Map, impl Fn(T) -> U>; - let mut _13: std::option::Option; - let _15: (); + let mut _12: std::option::Option; + let _14: (); + let mut _15: &mut std::iter::Map, impl Fn(T) -> U>; scope 1 { debug iter => _4; - let _14: U; + let _13: U; scope 2 { - debug x => _14; + debug x => _13; } scope 4 (inlined , impl Fn(T) -> U> as Iterator>::next) { - debug self => _5; - let mut _6: &mut impl Iterator; - let mut _7: std::option::Option; - let mut _8: &mut impl Fn(T) -> U; + debug self => _15; + let mut _5: &mut impl Iterator; + let mut _6: std::option::Option; + let mut _7: &mut impl Fn(T) -> U; scope 5 (inlined Option::::map:: U>) { - debug self => _7; - debug f => _8; - let mut _9: isize; - let _10: T; - let mut _11: (T,); - let mut _12: U; + debug self => _6; + debug f => _7; + let mut _8: isize; + let _9: T; + let mut _10: (T,); + let mut _11: U; scope 6 { - debug x => _10; + debug x => _9; scope 7 (inlined ops::function::impls:: for &mut impl Fn(T) -> U>::call_once) { - debug self => _8; - debug args => _11; + debug self => _7; + debug args => _10; } } } @@ -52,30 +52,30 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { } bb2: { - StorageLive(_13); - _5 = &mut _4; - StorageLive(_8); + StorageLive(_12); + Nop(Assign((_15, &mut _4))); StorageLive(_7); StorageLive(_6); - _6 = &mut (_4.0: impl Iterator); - _7 = as Iterator>::next(move _6) -> [return: bb3, unwind: bb10]; + StorageLive(_5); + _5 = &mut (_4.0: impl Iterator); + _6 = as Iterator>::next(move _5) -> [return: bb3, unwind: bb10]; } bb3: { - StorageDead(_6); - _8 = &mut (_4.1: impl Fn(T) -> U); + StorageDead(_5); + _7 = &mut (_4.1: impl Fn(T) -> U); + StorageLive(_8); StorageLive(_9); - StorageLive(_10); - _9 = discriminant(_7); - switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb9]; + _8 = discriminant(_6); + switchInt(move _8) -> [0: bb4, 1: bb6, otherwise: bb9]; } bb4: { - StorageDead(_10); StorageDead(_9); - StorageDead(_7); StorageDead(_8); - StorageDead(_13); + StorageDead(_6); + StorageDead(_7); + StorageDead(_12); drop(_4) -> [return: bb5, unwind continue]; } @@ -85,27 +85,27 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { } bb6: { - _10 = move ((_7 as Some).0: T); - StorageLive(_12); + _9 = move ((_6 as Some).0: T); StorageLive(_11); - _11 = (copy _10,); - _12 = U as FnMut<(T,)>>::call_mut(move _8, move _11) -> [return: bb7, unwind: bb10]; + StorageLive(_10); + _10 = (copy _9,); + _11 = U as FnMut<(T,)>>::call_mut(move _7, move _10) -> [return: bb7, unwind: bb10]; } bb7: { - StorageDead(_11); - _13 = Option::::Some(move _12); - StorageDead(_12); StorageDead(_10); + _12 = Option::::Some(move _11); + StorageDead(_11); StorageDead(_9); - StorageDead(_7); StorageDead(_8); - _14 = move ((_13 as Some).0: U); - _15 = opaque::(move _14) -> [return: bb8, unwind: bb10]; + StorageDead(_6); + StorageDead(_7); + _13 = move ((_12 as Some).0: U); + _14 = opaque::(move _13) -> [return: bb8, unwind: bb10]; } bb8: { - StorageDead(_13); + StorageDead(_12); goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index cbdd194afd3ab..dc57370366d7e 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -3,183 +3,164 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2: &&(usize, usize, usize, usize)) -> bool { let mut _0: bool; let mut _3: &(usize, usize, usize, usize); - let _4: &usize; - let _5: &usize; - let _6: &usize; - let _7: &usize; - let mut _8: &&usize; - let _9: &usize; - let mut _10: &&usize; - let mut _13: bool; - let mut _14: &&usize; + let mut _6: bool; + let mut _9: bool; + let mut _10: bool; + let _13: &usize; + let _14: &usize; let _15: &usize; - let mut _16: &&usize; - let mut _19: bool; + let _16: &usize; + let mut _17: &&usize; + let mut _18: &&usize; + let mut _19: &&usize; let mut _20: &&usize; - let _21: &usize; + let mut _21: &&usize; let mut _22: &&usize; - let mut _23: bool; + let mut _23: &&usize; let mut _24: &&usize; - let _25: &usize; - let mut _26: &&usize; scope 1 { - debug a => _4; - debug b => _5; - debug c => _6; - debug d => _7; + debug a => _13; + debug b => _14; + debug c => _15; + debug d => _16; scope 2 (inlined std::cmp::impls::::le) { - debug self => _8; - debug other => _10; + debug self => _17; + debug other => _18; scope 3 (inlined std::cmp::impls::::le) { - debug self => _4; - debug other => _6; - let mut _11: usize; - let mut _12: usize; + debug self => _13; + debug other => _15; + let mut _4: usize; + let mut _5: usize; } } scope 4 (inlined std::cmp::impls::::le) { - debug self => _14; - debug other => _16; + debug self => _19; + debug other => _20; scope 5 (inlined std::cmp::impls::::le) { - debug self => _7; - debug other => _5; - let mut _17: usize; - let mut _18: usize; + debug self => _16; + debug other => _14; + let mut _7: usize; + let mut _8: usize; } } scope 6 (inlined std::cmp::impls::::le) { - debug self => _20; + debug self => _21; debug other => _22; scope 7 (inlined std::cmp::impls::::le) { - debug self => _6; - debug other => _4; + debug self => _15; + debug other => _13; } } scope 8 (inlined std::cmp::impls::::le) { - debug self => _24; - debug other => _26; + debug self => _23; + debug other => _24; scope 9 (inlined std::cmp::impls::::le) { - debug self => _5; - debug other => _7; - let mut _27: usize; - let mut _28: usize; + debug self => _14; + debug other => _16; + let mut _11: usize; + let mut _12: usize; } } } bb0: { _3 = copy (*_2); - _4 = &((*_3).0: usize); - _5 = &((*_3).1: usize); - _6 = &((*_3).2: usize); - _7 = &((*_3).3: usize); - StorageLive(_13); - StorageLive(_8); - _8 = &_4; - StorageLive(_10); - StorageLive(_9); - _9 = copy _6; - _10 = &_9; - _11 = copy ((*_3).0: usize); - _12 = copy ((*_3).2: usize); - _13 = Le(copy _11, copy _12); - switchInt(move _13) -> [0: bb1, otherwise: bb2]; + Nop(Assign((_13, &((*_3).0: usize)))); + Nop(Assign((_14, &((*_3).1: usize)))); + Nop(Assign((_15, &((*_3).2: usize)))); + Nop(Assign((_16, &((*_3).3: usize)))); + StorageLive(_6); + StorageLive(_17); + Nop(Assign((_17, &_13))); + StorageLive(_18); + Nop(Assign((_18, &_15))); + _4 = copy ((*_3).0: usize); + _5 = copy ((*_3).2: usize); + _6 = Le(copy _4, copy _5); + switchInt(move _6) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageDead(_9); - StorageDead(_10); - StorageDead(_8); + StorageDead(_18); + StorageDead(_17); goto -> bb4; } bb2: { - StorageDead(_9); - StorageDead(_10); - StorageDead(_8); - StorageLive(_19); - StorageLive(_14); - _14 = &_7; - StorageLive(_16); - StorageLive(_15); - _15 = copy _5; - _16 = &_15; - StorageLive(_17); - _17 = copy ((*_3).3: usize); - StorageLive(_18); - _18 = copy ((*_3).1: usize); - _19 = Le(move _17, move _18); StorageDead(_18); StorageDead(_17); - switchInt(move _19) -> [0: bb3, otherwise: bb8]; + StorageLive(_9); + StorageLive(_19); + Nop(Assign((_19, &_16))); + StorageLive(_20); + Nop(Assign((_20, &_14))); + StorageLive(_7); + _7 = copy ((*_3).3: usize); + StorageLive(_8); + _8 = copy ((*_3).1: usize); + _9 = Le(move _7, move _8); + StorageDead(_8); + StorageDead(_7); + switchInt(move _9) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_15); - StorageDead(_16); - StorageDead(_14); + StorageDead(_20); + StorageDead(_19); goto -> bb4; } bb4: { - StorageLive(_23); - StorageLive(_20); - _20 = &_6; - StorageLive(_22); + StorageLive(_10); StorageLive(_21); - _21 = copy _4; - _22 = &_21; - _23 = Le(copy _12, copy _11); - switchInt(move _23) -> [0: bb5, otherwise: bb6]; + Nop(Assign((_21, &_15))); + StorageLive(_22); + Nop(Assign((_22, &_13))); + _10 = Le(copy _5, copy _4); + switchInt(move _10) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_21); StorageDead(_22); - StorageDead(_20); + StorageDead(_21); _0 = const false; goto -> bb7; } bb6: { - StorageDead(_21); StorageDead(_22); - StorageDead(_20); + StorageDead(_21); + StorageLive(_23); + Nop(Assign((_23, &_14))); StorageLive(_24); - _24 = &_5; - StorageLive(_26); - StorageLive(_25); - _25 = copy _7; - _26 = &_25; - StorageLive(_27); - _27 = copy ((*_3).1: usize); - StorageLive(_28); - _28 = copy ((*_3).3: usize); - _0 = Le(move _27, move _28); - StorageDead(_28); - StorageDead(_27); - StorageDead(_25); - StorageDead(_26); + Nop(Assign((_24, &_16))); + StorageLive(_11); + _11 = copy ((*_3).1: usize); + StorageLive(_12); + _12 = copy ((*_3).3: usize); + _0 = Le(move _11, move _12); + StorageDead(_12); + StorageDead(_11); StorageDead(_24); + StorageDead(_23); goto -> bb7; } bb7: { - StorageDead(_23); + StorageDead(_10); goto -> bb9; } bb8: { - StorageDead(_15); - StorageDead(_16); - StorageDead(_14); + StorageDead(_20); + StorageDead(_19); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_19); - StorageDead(_13); + StorageDead(_9); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir index fe4e2deab8706..2a12e8d73b018 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir @@ -9,7 +9,7 @@ fn outer(_1: u8) -> u8 { } bb0: { - _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 + Nop(Assign((_2, &_1))); // scope 0 at $DIR/spans.rs:11:11: 11:13 _0 = copy _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index fe4e2deab8706..2a12e8d73b018 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -9,7 +9,7 @@ fn outer(_1: u8) -> u8 { } bb0: { - _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 + Nop(Assign((_2, &_1))); // scope 0 at $DIR/spans.rs:11:11: 11:13 _0 = copy _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } From 081e59cf974128a9c1a6ba13ed59d342e0480b4f Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 21 Apr 2025 22:05:53 +0800 Subject: [PATCH 3/4] codegen: ignore unsupported var debuginfo projection --- compiler/rustc_codegen_ssa/src/mir/debuginfo.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 5924c8991ad64..4b3a429b48824 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -205,7 +205,8 @@ fn calculate_debuginfo_offset< _ => { // Sanity check for `can_use_in_debuginfo`. assert!(!elem.can_use_in_debuginfo()); - bug!("unsupported var debuginfo projection `{:?}`", projection) + // TODO: Temporarily disabled for testing purposes. + // bug!("unsupported var debuginfo projection `{:?}`", projection) } } } From a456a6552cc956ae63d7c4061ffd263cf85ac08d Mon Sep 17 00:00:00 2001 From: dianqk Date: Wed, 16 Apr 2025 22:19:17 +0800 Subject: [PATCH 4/4] codegen: emit the debugging information for the dead code --- compiler/rustc_codegen_gcc/src/debuginfo.rs | 3 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 38 +++++++---- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 10 +++ .../rustc_codegen_ssa/src/mir/debuginfo.rs | 51 ++++++++++++++- .../rustc_codegen_ssa/src/mir/statement.rs | 65 ++++++++++++++++++- .../rustc_codegen_ssa/src/traits/debuginfo.rs | 3 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 12 ++++ ...y.run2-{closure#0}.Inline.panic-abort.diff | 6 -- ...implifyComparisonIntegral.panic-abort.diff | 6 -- 9 files changed, 163 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 55e01687400aa..e61874fd0994e 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -26,7 +26,8 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { &mut self, _dbg_var: Self::DIVariable, _dbg_loc: Self::DILocation, - _variable_alloca: Self::Value, + _is_declared: bool, + _val: Self::Value, _direct_offset: Size, _indirect_offsets: &[Size], _fragment: Option>, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index c508592792347..c0cc754c31ae9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -154,7 +154,8 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { &mut self, dbg_var: &'ll DIVariable, dbg_loc: &'ll DILocation, - variable_alloca: Self::Value, + is_declared: bool, + val: Self::Value, direct_offset: Size, indirect_offsets: &[Size], fragment: Option>, @@ -183,17 +184,30 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { addr_ops.push((fragment.end - fragment.start).bits() as u64); } - unsafe { - // FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`. - llvm::LLVMRustDIBuilderInsertDeclareAtEnd( - DIB(self.cx()), - variable_alloca, - dbg_var, - addr_ops.as_ptr(), - addr_ops.len() as c_uint, - dbg_loc, - self.llbb(), - ); + if is_declared { + unsafe { + llvm::LLVMRustDIBuilderInsertDeclareAtEnd( + DIB(self.cx()), + val, + dbg_var, + addr_ops.as_ptr(), + addr_ops.len() as c_uint, + dbg_loc, + self.llbb(), + ); + } + } else { + unsafe { + llvm::LLVMRustDIBuilderInsertDbgValueAtEnd( + DIB(self.cx()), + val, + dbg_var, + addr_ops.as_ptr(), + addr_ops.len() as c_uint, + dbg_loc, + self.llbb(), + ); + } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 9ff04f729030c..dd6efe0fd3453 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2301,6 +2301,16 @@ unsafe extern "C" { InsertAtEnd: &'a BasicBlock, ); + pub(crate) fn LLVMRustDIBuilderInsertDbgValueAtEnd<'a>( + Builder: &DIBuilder<'a>, + Val: &'a Value, + VarInfo: &'a DIVariable, + AddrOps: *const u64, + AddrOpsCount: c_uint, + DL: &'a DILocation, + InsertAtEnd: &'a BasicBlock, + ); + pub(crate) fn LLVMRustDIBuilderCreateEnumerator<'a>( Builder: &DIBuilder<'a>, Name: *const c_char, diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 4b3a429b48824..643ad95cf3f9f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -378,6 +378,52 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + pub(crate) fn debug_new_value_to_local( + &self, + bx: &mut Bx, + local: mir::Local, + base: PlaceValue, + layout: TyAndLayout<'tcx>, + projection: &[mir::PlaceElem<'tcx>], + ) { + let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full; + if !full_debug_info { + return; + } + + let vars = match &self.per_local_var_debug_info { + Some(per_local) => &per_local[local], + None => return, + }; + + for var in vars.iter().cloned() { + self.debug_new_value_to_local_as_var(bx, base, layout, projection, var); + } + } + + fn debug_new_value_to_local_as_var( + &self, + bx: &mut Bx, + base: PlaceValue, + layout: TyAndLayout<'tcx>, + projection: &[mir::PlaceElem<'tcx>], + var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>, + ) { + let Some(dbg_var) = var.dbg_var else { return }; + let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return }; + let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } = + calculate_debuginfo_offset(bx, projection, layout); + bx.dbg_var_addr( + dbg_var, + dbg_loc, + false, + base.llval, + direct_offset, + &indirect_offsets, + var.fragment, + ); + } + fn debug_introduce_local_as_var( &self, bx: &mut Bx, @@ -387,7 +433,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) { let Some(dbg_var) = var.dbg_var else { return }; let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return }; - let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } = calculate_debuginfo_offset(bx, var.projection, base.layout); @@ -422,6 +467,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.dbg_var_addr( dbg_var, dbg_loc, + true, alloca.val.llval, Size::ZERO, &[Size::ZERO], @@ -431,6 +477,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.dbg_var_addr( dbg_var, dbg_loc, + true, base.val.llval, direct_offset, &indirect_offsets, @@ -456,7 +503,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let base = FunctionCx::spill_operand_to_stack(operand, Some(name), bx); bx.clear_dbg_loc(); - bx.dbg_var_addr(dbg_var, dbg_loc, base.val.llval, Size::ZERO, &[], fragment); + bx.dbg_var_addr(dbg_var, dbg_loc, true, base.val.llval, Size::ZERO, &[], fragment); } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index ebc088f7bcb89..fa0c4c9a406bb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,8 +1,10 @@ use rustc_middle::mir::{self, NonDivergingIntrinsic}; -use rustc_middle::span_bug; +use rustc_middle::{bug, span_bug}; use tracing::instrument; use super::{FunctionCx, LocalRef}; +use crate::mir::operand::OperandValue; +use crate::mir::place::PlaceRef; use crate::traits::*; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { @@ -94,8 +96,65 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | mir::StatementKind::PlaceMention(..) | mir::StatementKind::BackwardIncompatibleDropHint { .. } => {} mir::StatementKind::Nop(ref stmt) => { - if stmt.is_some() { - todo!("add debugging information") + if let Some(box stmt_kind) = stmt { + match stmt_kind { + mir::StatementKind::Assign(box (dest, rvalue)) => { + if let Some(index) = dest.as_local() + && let mir::Rvalue::Ref(_, _, place) = *rvalue + { + let place_ref = match self.locals[place.local] { + LocalRef::Place(place_ref) + | LocalRef::UnsizedPlace(place_ref) => Some(place_ref), + LocalRef::Operand(operand_ref) => match operand_ref.val { + OperandValue::Ref(_place_value) => { + todo!("OperandValue::Ref") + } + OperandValue::Immediate(v) => { + Some(PlaceRef::new_sized(v, operand_ref.layout)) + } + OperandValue::Pair(_, _) => None, + OperandValue::ZeroSized => None, + }, + LocalRef::PendingOperand => None, + }; + let (val, layout, projection) = + match (place_ref, place.is_indirect_first_projection()) { + (Some(place_ref), false) => ( + place_ref.val, + place_ref.layout, + place.projection.as_slice(), + ), + (Some(place_ref), true) => { + let projected_ty = place_ref + .layout + .ty + .builtin_deref(true) + .unwrap_or_else(|| { + bug!("deref of non-pointer {:?}", place_ref) + }); + let layout = bx.cx().layout_of(projected_ty); + (place_ref.val, layout, &place.projection[1..]) + } + _ => { + let ty = + self.monomorphize(self.mir.local_decls[index].ty); + let layout = bx.cx().layout_of(ty); + let to_backend_ty = + bx.cx().immediate_backend_type(layout); + let place_ref = PlaceRef::new_sized( + bx.cx().const_poison(to_backend_ty), + layout, + ); + (place_ref.val, layout, [].as_slice()) + } + }; + self.debug_new_value_to_local(bx, index, val, layout, projection); + } else { + todo!("add debugging information") + } + } + _ => {} + } } } } diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index 30d77c206a56f..bdefa99b6f7ed 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -71,7 +71,8 @@ pub trait DebugInfoBuilderMethods: BackendTypes { &mut self, dbg_var: Self::DIVariable, dbg_loc: Self::DILocation, - variable_alloca: Self::Value, + is_declared: bool, + val: Self::Value, direct_offset: Size, // NB: each offset implies a deref (i.e. they're steps in a pointer chain). indirect_offsets: &[Size], diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 5f0e4d745e833..3d32c28f4fb4f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1247,6 +1247,18 @@ LLVMRustDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef V, DebugLoc(cast(unwrap(DL))), unwrap(InsertAtEnd)); } +extern "C" void +LLVMRustDIBuilderInsertDbgValueAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef V, + LLVMMetadataRef VarInfo, uint64_t *AddrOps, + unsigned AddrOpsCount, LLVMMetadataRef DL, + LLVMBasicBlockRef InsertAtEnd) { + unwrap(Builder)->insertDbgValueIntrinsic( + unwrap(V), unwrap(VarInfo), + unwrap(Builder)->createExpression( + llvm::ArrayRef(AddrOps, AddrOpsCount)), + DebugLoc(cast(unwrap(DL))), unwrap(InsertAtEnd)); +} + extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder, const char *Name, size_t NameLen, const uint64_t Value[2], diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index bbfa1b75c9625..63d2942602dc9 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -227,23 +227,18 @@ + _22 = &mut (*_23); + StorageDead(_24); + StorageLive(_45); -+ StorageLive(_46); + StorageLive(_50); + StorageLive(_42); + StorageLive(_43); -+ StorageLive(_44); + Nop(Assign((_46, &mut _19))); -+ StorageLive(_47); + Nop(Assign((_47, &mut (_19.0: &mut std::future::Ready<()>)))); + _45 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_47); + Nop(Assign((_44, &mut ((*_45).0: std::option::Option<()>)))); + StorageLive(_48); + _48 = Option::<()>::None; + _43 = copy ((*_45).0: std::option::Option<()>); + ((*_45).0: std::option::Option<()>) = copy _48; + StorageDead(_48); -+ StorageDead(_44); + StorageLive(_49); + _49 = discriminant(_43); + switchInt(move _49) -> [0: bb11, 1: bb12, otherwise: bb5]; @@ -319,7 +314,6 @@ + _18 = Poll::<()>::Ready(move _42); + StorageDead(_42); + StorageDead(_50); -+ StorageDead(_46); + StorageDead(_45); + StorageDead(_22); + StorageDead(_19); diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index 88f064291b799..8f6a237afb744 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -37,15 +37,9 @@ } bb2: { - StorageLive(_7); Nop(Assign((_7, &(*_2)[0 of 3]))); - StorageLive(_8); Nop(Assign((_8, &(*_2)[1 of 3]))); - StorageLive(_9); Nop(Assign((_9, &(*_2)[2 of 3]))); - StorageDead(_9); - StorageDead(_8); - StorageDead(_7); StorageDead(_4); return; }