mir-opt: Drop invalid debuginfos after SingleUseConsts.

This commit is contained in:
dianqk
2026-03-10 22:15:04 +08:00
parent 0c68443b0a
commit 86da9312dc
5 changed files with 96 additions and 20 deletions
+6 -5
View File
@@ -1050,11 +1050,12 @@ pub fn extend(&mut self, debuginfos: &Self) {
self.0.extend_from_slice(debuginfos);
}
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&StmtDebugInfo<'tcx>) -> bool,
{
self.0.retain(f);
pub fn retain_locals(&mut self, locals: &DenseBitSet<Local>) {
self.retain(|debuginfo| match debuginfo {
StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => {
locals.contains(*local)
}
});
}
}
@@ -5,6 +5,8 @@
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 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
);
}
}
drop_invalid_debuginfos(body);
}
fn is_required(&self) -> bool {
@@ -32,24 +32,21 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
)
});
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);
}
}
@@ -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;
}
}
@@ -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 <https://github.com/rust-lang/rust/issues/33013>.
#![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;
}