Replace locals in debuginfo records during ref_prop

This commit is contained in:
dianqk 2025-10-09 21:53:05 +08:00
parent 9462e7301f
commit b2e81b00e5
No known key found for this signature in database
5 changed files with 49 additions and 16 deletions

View file

@ -1098,6 +1098,10 @@ macro_rules! super_body {
}
}
for var_debug_info in &$($mutability)? $body.var_debug_info {
$self.visit_var_debug_info(var_debug_info);
}
for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
$self.visit_basic_block_data(bb, data);
}
@ -1127,10 +1131,6 @@ macro_rules! super_body {
);
}
for var_debug_info in &$($mutability)? $body.var_debug_info {
$self.visit_var_debug_info(var_debug_info);
}
$self.visit_span($(& $mutability)? $body.span);
if let Some(required_consts) = &$($mutability)? $body.required_consts {

View file

@ -302,6 +302,7 @@ fn compute_replacement<'tcx>(
return Replacer {
tcx,
targets: finder.targets,
remap_var_debug_infos: IndexVec::from_elem(None, body.local_decls()),
storage_to_remove,
allowed_replacements,
any_replacement: false,
@ -381,6 +382,7 @@ fn fully_replaceable_locals(ssa: &SsaLocals) -> DenseBitSet<Local> {
struct Replacer<'tcx> {
tcx: TyCtxt<'tcx>,
targets: IndexVec<Local, Value<'tcx>>,
remap_var_debug_infos: IndexVec<Local, Option<Local>>,
storage_to_remove: DenseBitSet<Local>,
allowed_replacements: FxHashSet<(Local, Location)>,
any_replacement: bool,
@ -392,21 +394,45 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
}
fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
// If the debuginfo is a pointer to another place
// and it's a reborrow: see through it
while let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
&& place.projection.is_empty()
&& let Value::Pointer(target, _) = self.targets[place.local]
&& let &[PlaceElem::Deref] = &target.projection[..]
{
*place = Place::from(target.local);
self.any_replacement = true;
let mut new_local = place.local;
// If the debuginfo is a pointer to another place
// and it's a reborrow: see through it
while let Value::Pointer(target, _) = self.targets[new_local]
&& let &[PlaceElem::Deref] = &target.projection[..]
{
new_local = target.local;
}
if place.local != new_local {
self.remap_var_debug_infos[place.local] = Some(new_local);
place.local = new_local;
self.any_replacement = true;
}
}
// Simplify eventual projections left inside `debuginfo`.
self.super_var_debug_info(debuginfo);
}
fn visit_statement_debuginfo(
&mut self,
stmt_debuginfo: &mut StmtDebugInfo<'tcx>,
location: Location,
) {
let local = match stmt_debuginfo {
StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => local,
};
if let Some(target) = self.remap_var_debug_infos[*local] {
*local = target;
self.any_replacement = true;
}
self.super_statement_debuginfo(stmt_debuginfo, location);
}
fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
loop {
let Some((&PlaceElem::Deref, rest)) = place.projection.split_first() else { return };
@ -437,8 +463,9 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
{
stmt.make_nop(true);
}
// Do not remove assignments as they may still be useful for debuginfo.
_ => self.super_statement(stmt, loc),
_ => {}
}
// Do not remove assignments as they may still be useful for debuginfo.
self.super_statement(stmt, loc);
}
}

View file

@ -25,7 +25,7 @@
- StorageDead(_2);
- StorageDead(_3);
- StorageDead(_1);
+ // DBG: _1 = &(*_5);
+ // DBG: _5 = &(*_5);
_0 = const ();
return;
}

View file

@ -1,4 +1,3 @@
// skip-filecheck
//@ test-mir-pass: ReferencePropagation
//@ compile-flags: -g -Zub_checks=false -Zinline-mir -Zmir-enable-passes=+DeadStoreElimination-initial
@ -9,6 +8,11 @@ use std::intrinsics::mir::*;
// EMIT_MIR ref_prop.remap_debuginfo_locals.ReferencePropagation.diff
pub fn remap_debuginfo_locals() {
// CHECK-LABEL: fn remap_debuginfo_locals()
// CHECK: debug a => [[a:_.*]];
// CHECK: bb0:
// CHECK-NEXT: [[a]] = const
// CHECK-NEXT: DBG: [[a]] = &(*[[a]]);
foo(&0);
}

View file

@ -1,6 +1,8 @@
//@ known-bug: #147485
//@ build-pass
//@ compile-flags: -g -O
// Regression test for #147485.
#![crate_type = "lib"]
pub fn f(x: *const usize) -> &'static usize {