Skip to content

Commit 224fbe9

Browse files
committed
fixup! mir-opt: Eliminate dead statements even if they are used by debuginfos
- duplicate the StmtDebugInfo arm, a None and a Some version - iter projections for invalid place
1 parent 432d579 commit 224fbe9

File tree

6 files changed

+82
-71
lines changed

6 files changed

+82
-71
lines changed

compiler/rustc_codegen_ssa/src/mir/statement.rs

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -109,44 +109,41 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
109109
pub(crate) fn codegen_stmt_debuginfo(&mut self, bx: &mut Bx, debuginfo: &StmtDebugInfo<'tcx>) {
110110
match debuginfo {
111111
StmtDebugInfo::AssignRef(dest, place) => {
112-
let assign_ref = if let Some(place) = place {
113-
let place_ref = match self.locals[place.local] {
114-
LocalRef::Place(place_ref) | LocalRef::UnsizedPlace(place_ref) => {
115-
Some(place_ref)
116-
}
117-
LocalRef::Operand(operand_ref) => match operand_ref.val {
118-
OperandValue::Immediate(v) => {
119-
Some(PlaceRef::new_sized(v, operand_ref.layout))
120-
}
121-
OperandValue::Ref(_)
122-
| OperandValue::Pair(_, _)
123-
| OperandValue::ZeroSized => None,
124-
},
125-
LocalRef::PendingOperand => None,
112+
let place_ref = match self.locals[place.local] {
113+
LocalRef::Place(place_ref) | LocalRef::UnsizedPlace(place_ref) => {
114+
Some(place_ref)
126115
}
127-
.filter(|place_ref| {
128-
// Drop unsupported projections.
129-
// FIXME: Add a test case.
130-
place.projection.iter().all(|p| p.can_use_in_debuginfo()) &&
116+
LocalRef::Operand(operand_ref) => match operand_ref.val {
117+
OperandValue::Immediate(v) => {
118+
Some(PlaceRef::new_sized(v, operand_ref.layout))
119+
}
120+
OperandValue::Ref(_)
121+
| OperandValue::Pair(_, _)
122+
| OperandValue::ZeroSized => None,
123+
},
124+
LocalRef::PendingOperand => None,
125+
}
126+
.filter(|place_ref| {
127+
// Drop unsupported projections.
128+
// FIXME: Add a test case.
129+
place.projection.iter().all(|p| p.can_use_in_debuginfo()) &&
131130
// Only pointers can calculate addresses.
132131
bx.type_kind(bx.val_ty(place_ref.val.llval)) == TypeKind::Pointer
133-
});
134-
match (place_ref, place.is_indirect_first_projection()) {
135-
(Some(place_ref), false) => {
136-
Some((place_ref.val, place_ref.layout, place.projection.as_slice()))
137-
}
138-
(Some(place_ref), true) => {
139-
let projected_ty =
140-
place_ref.layout.ty.builtin_deref(true).unwrap_or_else(|| {
141-
bug!("deref of non-pointer {:?}", place_ref)
142-
});
143-
let layout = bx.cx().layout_of(projected_ty);
144-
Some((place_ref.val, layout, &place.projection[1..]))
145-
}
146-
_ => None,
132+
});
133+
let assign_ref = match (place_ref, place.is_indirect_first_projection()) {
134+
(Some(place_ref), false) => {
135+
Some((place_ref.val, place_ref.layout, place.projection.as_slice()))
147136
}
148-
} else {
149-
None
137+
(Some(place_ref), true) => {
138+
let projected_ty = place_ref
139+
.layout
140+
.ty
141+
.builtin_deref(true)
142+
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", place_ref));
143+
let layout = bx.cx().layout_of(projected_ty);
144+
Some((place_ref.val, layout, &place.projection[1..]))
145+
}
146+
_ => None,
150147
};
151148
let (val, layout, projection) = assign_ref.unwrap_or_else(|| {
152149
// If the address cannot be computed, use poison to indicate that the value has been optimized out.
@@ -159,6 +156,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
159156
});
160157
self.debug_new_value_to_local(bx, *dest, val, layout, projection);
161158
}
159+
StmtDebugInfo::InvalidAssign(local) => {
160+
let ty = self.monomorphize(self.mir.local_decls[*local].ty);
161+
let layout = bx.cx().layout_of(ty);
162+
let to_backend_ty = bx.cx().immediate_backend_type(layout);
163+
let place_ref = PlaceRef::new_sized(bx.cx().const_poison(to_backend_ty), layout);
164+
self.debug_new_value_to_local(bx, *local, place_ref.val, layout, &[]);
165+
}
162166
}
163167
}
164168

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,10 @@ impl Debug for StmtDebugInfo<'_> {
901901
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
902902
match self {
903903
StmtDebugInfo::AssignRef(local, place) => {
904-
write!(fmt, "{local:?} = &")?;
905-
if let Some(place) = place { write!(fmt, "{place:?}") } else { write!(fmt, "?") }
904+
write!(fmt, "{local:?} = &{place:?}")
905+
}
906+
StmtDebugInfo::InvalidAssign(local) => {
907+
write!(fmt, "{local:?} = &?")
906908
}
907909
}
908910
}

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<'tcx> StatementKind<'tcx> {
8282
StatementKind::Assign(box (place, Rvalue::Ref(_, _, ref_place)))
8383
if let Some(local) = place.as_local() =>
8484
{
85-
Some(StmtDebugInfo::AssignRef(local, Some(*ref_place)))
85+
Some(StmtDebugInfo::AssignRef(local, *ref_place))
8686
}
8787
_ => None,
8888
}
@@ -498,6 +498,21 @@ impl<'tcx> PlaceRef<'tcx> {
498498
})
499499
}
500500

501+
/// Return the place accessed locals that include the base local.
502+
pub fn accessed_locals(self) -> impl Iterator<Item = Local> {
503+
std::iter::once(self.local).chain(self.projection.iter().filter_map(|proj| match proj {
504+
ProjectionElem::Index(local) => Some(*local),
505+
ProjectionElem::Deref
506+
| ProjectionElem::Field(_, _)
507+
| ProjectionElem::ConstantIndex { .. }
508+
| ProjectionElem::Subslice { .. }
509+
| ProjectionElem::Downcast(_, _)
510+
| ProjectionElem::OpaqueCast(_)
511+
| ProjectionElem::UnwrapUnsafeBinder(_)
512+
| ProjectionElem::Subtype(_) => None,
513+
}))
514+
}
515+
501516
/// Generates a new place by appending `more_projections` to the existing ones
502517
/// and interning the result.
503518
pub fn project_deeper(
@@ -1028,5 +1043,6 @@ impl<'tcx> ops::DerefMut for StmtDebugInfos<'tcx> {
10281043

10291044
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
10301045
pub enum StmtDebugInfo<'tcx> {
1031-
AssignRef(Local, Option<Place<'tcx>>),
1046+
AssignRef(Local, Place<'tcx>),
1047+
InvalidAssign(Local),
10321048
}

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -400,14 +400,19 @@ macro_rules! make_mir_visitor {
400400
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
401401
location
402402
);
403-
if let Some(place) = place {
404-
self.visit_place(
405-
place,
406-
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
407-
location
408-
);
409-
}
403+
self.visit_place(
404+
place,
405+
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
406+
location
407+
);
410408
},
409+
StmtDebugInfo::InvalidAssign(local) => {
410+
self.visit_local(
411+
$(& $mutability)? *local,
412+
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
413+
location
414+
);
415+
}
411416
}
412417
}
413418

compiler/rustc_mir_transform/src/simplify.rs

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -653,19 +653,6 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod
653653
}
654654
}
655655

656-
struct InvalidPlace<'a> {
657-
map: &'a IndexVec<Local, Option<Local>>,
658-
is_invalid: bool,
659-
}
660-
661-
impl<'tcx, 'a> Visitor<'tcx> for InvalidPlace<'a> {
662-
fn visit_local(&mut self, local: Local, _: PlaceContext, _: Location) {
663-
if self.map[local].is_none() {
664-
self.is_invalid = true;
665-
}
666-
}
667-
}
668-
669656
struct LocalUpdater<'tcx> {
670657
map: IndexVec<Local, Option<Local>>,
671658
tcx: TyCtxt<'tcx>,
@@ -682,19 +669,12 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
682669
location: Location,
683670
) {
684671
match stmt_debuginfo {
685-
StmtDebugInfo::AssignRef(_, place) => {
686-
if place.is_some_and(|ref place| {
687-
let mut invalid_place = InvalidPlace { map: &self.map, is_invalid: false };
688-
invalid_place.visit_place(
689-
place,
690-
PlaceContext::NonUse(visit::NonUseContext::VarDebugInfo),
691-
location,
692-
);
693-
invalid_place.is_invalid
694-
}) {
695-
*place = None;
672+
StmtDebugInfo::AssignRef(local, place) => {
673+
if place.as_ref().accessed_locals().any(|local| self.map[local].is_none()) {
674+
*stmt_debuginfo = StmtDebugInfo::InvalidAssign(*local);
696675
}
697676
}
677+
StmtDebugInfo::InvalidAssign(_) => {}
698678
}
699679
self.super_statement_debuginfo(stmt_debuginfo, location);
700680
}

compiler/rustc_mir_transform/src/strip_debuginfo.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
3636
for data in body.basic_blocks.as_mut_preserves_cfg() {
3737
for stmt in data.statements.iter_mut() {
3838
stmt.debuginfos.retain(|debuginfo| match debuginfo {
39-
StmtDebugInfo::AssignRef(local, _) => debuginfo_locals.contains(*local),
39+
StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => {
40+
debuginfo_locals.contains(*local)
41+
}
4042
});
4143
}
4244
data.after_last_stmt_debuginfos.retain(|debuginfo| match debuginfo {
43-
StmtDebugInfo::AssignRef(local, _) => debuginfo_locals.contains(*local),
45+
StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => {
46+
debuginfo_locals.contains(*local)
47+
}
4448
});
4549
}
4650
}

0 commit comments

Comments
 (0)