diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 48dcef298d66a..f66c4755de4dd 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -1050,11 +1050,12 @@ impl<'tcx> StmtDebugInfos<'tcx> { self.0.extend_from_slice(debuginfos); } - pub fn retain(&mut self, f: F) - where - F: FnMut(&StmtDebugInfo<'tcx>) -> bool, - { - self.0.retain(f); + pub fn retain_locals(&mut self, locals: &DenseBitSet) { + self.retain(|debuginfo| match debuginfo { + StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { + locals.contains(*local) + } + }); } } diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 6d33736d64ecb..91e040d5cbc89 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -5,6 +5,8 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use crate::strip_debuginfo::drop_invalid_debuginfos; + /// Various parts of MIR building introduce temporaries that are commonly not needed. /// /// Notably, `if CONST` and `match CONST` end up being used-once temporaries, which @@ -82,6 +84,8 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { ); } } + + drop_invalid_debuginfos(body); } fn is_required(&self) -> bool { diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs index 7fec25ccb5218..5931a46660241 100644 --- a/compiler/rustc_mir_transform/src/strip_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs @@ -32,24 +32,21 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { ) }); - 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) - } - }); - } + drop_invalid_debuginfos(body); } fn is_required(&self) -> bool { true } } + +// Drop invalid debuginfos when strip locals in `var_debug_info`. +pub(super) fn drop_invalid_debuginfos(body: &mut Body<'_>) { + 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_locals(&debuginfo_locals); + } + data.after_last_stmt_debuginfos.retain_locals(&debuginfo_locals); + } +} diff --git a/tests/mir-opt/debuginfo/single_use_consts.invalid_debuginfo.SingleUseConsts.diff b/tests/mir-opt/debuginfo/single_use_consts.invalid_debuginfo.SingleUseConsts.diff new file mode 100644 index 0000000000000..09e9f26546a85 --- /dev/null +++ b/tests/mir-opt/debuginfo/single_use_consts.invalid_debuginfo.SingleUseConsts.diff @@ -0,0 +1,49 @@ +- // MIR for `invalid_debuginfo` before SingleUseConsts ++ // MIR for `invalid_debuginfo` after SingleUseConsts + + fn invalid_debuginfo() -> () { + let mut _0: (); + let _1: (); + scope 1 (inlined foo) { + let _2: (); + let mut _3: &isize; + let _4: &isize; + let _5: isize; + let mut _6: &isize; + scope 2 (inlined bar) { +- debug x => _4; ++ debug x => const foo::promoted[0]; + let _7: isize; + let mut _9: &isize; + let _10: &isize; + scope 3 { +- debug a => _7; ++ debug a => const 1_isize; + let mut _8: &isize; + scope 4 { +- debug z => _4; ++ debug z => const foo::promoted[0]; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_4); +- _4 = const foo::promoted[0]; ++ nop; + StorageLive(_7); +- _7 = const 1_isize; +- // DBG: _4 = &_7; ++ nop; + StorageDead(_7); +- _1 = const (); ++ nop; + StorageDead(_4); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/single_use_consts.rs b/tests/mir-opt/debuginfo/single_use_consts.rs new file mode 100644 index 0000000000000..eeae4cb7b81c5 --- /dev/null +++ b/tests/mir-opt/debuginfo/single_use_consts.rs @@ -0,0 +1,25 @@ +//@ test-mir-pass: SingleUseConsts +//@ compile-flags: -g -Zinline-mir -Zmir-enable-passes=+InstSimplify-after-simplifycfg,+DeadStoreElimination-final,+DestinationPropagation -Zvalidate-mir +//! Regression test for . + +#![crate_type = "lib"] + +// EMIT_MIR single_use_consts.invalid_debuginfo.SingleUseConsts.diff +pub fn invalid_debuginfo() { + // CHECK-LABEL: fn invalid_debuginfo( + // CHEK: debug x => const + // CHEK: debug z => const + // CHECK-NOT: DBG + // CHECK: return + foo(); +} + +pub fn foo() { + bar(&1); +} + +fn bar(x: &isize) { + let a = 1; + let mut z = x; + z = &a; +}