Skip to content

Commit daf2968

Browse files
committed
Fix variable debuginfo being optimized away at mir-opt-level=2
The `DeadStoreElmination` pass was removing the uses of these locals because the are never used in the MIR body except for debuginfo. I've updated the pass to consider locals referenced by debuginfo as always alive unless a higher MIR opt level is requested by the user.
1 parent bebe274 commit daf2968

File tree

4 files changed

+59
-24
lines changed

4 files changed

+59
-24
lines changed

compiler/rustc_mir_transform/src/dead_store_elimination.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ use rustc_mir_dataflow::Analysis;
2020

2121
/// Performs the optimization on the body
2222
///
23-
/// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
23+
/// The `always_live` set must be a `BitSet` of all the locals that are considered always alive and
24+
/// never eliminated. This should be, at least, the set of locals which are ever borrowed in this
25+
/// body. It may include other locals as well if necessary. The minimum set of always alive locals
2426
/// can be generated via the [`borrowed_locals`] function.
25-
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
26-
let mut live = MaybeTransitiveLiveLocals::new(borrowed)
27+
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, always_live: &BitSet<Local>) {
28+
let mut live = MaybeTransitiveLiveLocals::new(always_live)
2729
.into_engine(tcx, body)
2830
.iterate_to_fixpoint()
2931
.into_results_cursor(body);
@@ -41,7 +43,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
4143
StatementKind::Assign(box (place, _))
4244
| StatementKind::SetDiscriminant { place: box place, .. }
4345
| StatementKind::Deinit(box place) => {
44-
if !place.is_indirect() && !borrowed.contains(place.local) {
46+
if !place.is_indirect() && !always_live.contains(place.local) {
4547
live.seek_before_primary_effect(loc);
4648
if !live.get().contains(place.local) {
4749
patch.push(loc);
@@ -80,7 +82,21 @@ impl<'tcx> MirPass<'tcx> for DeadStoreElimination {
8082
}
8183

8284
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
83-
let borrowed = borrowed_locals(body);
84-
eliminate(tcx, body, &borrowed);
85+
let mut always_live = borrowed_locals(body);
86+
87+
// Include any locals which are used by debuginfo unless we're at a high enough MIR opt
88+
// level that degrading debuginfo is acceptable.
89+
if tcx.sess.mir_opt_level() < 3 {
90+
for x in &body.var_debug_info {
91+
match x.value {
92+
VarDebugInfoContents::Place(p) => {
93+
always_live.insert(p.local);
94+
}
95+
VarDebugInfoContents::Const(..) => {}
96+
}
97+
}
98+
}
99+
100+
eliminate(tcx, body, &always_live);
85101
}
86102
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// compile-flags: -g -O
2+
3+
// Check that simple constant values are preserved in debuginfo across both MIR opts and LLVM opts
4+
5+
#![crate_type = "lib"]
6+
7+
#[no_mangle]
8+
pub fn check_it() {
9+
let a = 1;
10+
let b = 42;
11+
12+
foo(a + b);
13+
}
14+
15+
#[inline(never)]
16+
fn foo(x: i32) {
17+
std::process::exit(x);
18+
}
19+
20+
// CHECK-LABEL: @check_it
21+
// CHECK: call void @llvm.dbg.value(metadata i32 1, metadata ![[a_metadata:[0-9]+]], metadata !DIExpression())
22+
// CHECK: call void @llvm.dbg.value(metadata i32 42, metadata ![[b_metadata:[0-9]+]], metadata !DIExpression())
23+
24+
// CHECK: ![[a_metadata]] = !DILocalVariable(name: "a"
25+
// CHECK-SAME: line: 9
26+
27+
// CHECK: ![[b_metadata]] = !DILocalVariable(name: "b"
28+
// CHECK-SAME: line: 10

src/test/mir-opt/dead-store-elimination/constant_local_debuginfo.main.DeadStoreElimination.diff

+2-4
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@
1818

1919
bb0: {
2020
StorageLive(_1); // scope 0 at $DIR/constant-local-debuginfo.rs:+1:9: +1:10
21-
- _1 = const 1_i32; // scope 0 at $DIR/constant-local-debuginfo.rs:+1:13: +1:14
22-
+ nop; // scope 0 at $DIR/constant-local-debuginfo.rs:+1:13: +1:14
21+
_1 = const 1_i32; // scope 0 at $DIR/constant-local-debuginfo.rs:+1:13: +1:14
2322
StorageLive(_2); // scope 1 at $DIR/constant-local-debuginfo.rs:+2:9: +2:10
24-
- _2 = const 4_i32; // scope 1 at $DIR/constant-local-debuginfo.rs:+2:13: +2:14
25-
+ nop; // scope 1 at $DIR/constant-local-debuginfo.rs:+2:13: +2:14
23+
_2 = const 4_i32; // scope 1 at $DIR/constant-local-debuginfo.rs:+2:13: +2:14
2624
StorageLive(_3); // scope 2 at $DIR/constant-local-debuginfo.rs:+4:5: +4:15
2725
StorageLive(_4); // scope 2 at $DIR/constant-local-debuginfo.rs:+4:9: +4:14
2826
StorageLive(_5); // scope 2 at $DIR/constant-local-debuginfo.rs:+4:9: +4:10

src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff

+7-14
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,18 @@
3737

3838
bb3: {
3939
StorageLive(_6); // scope 0 at $DIR/cycle.rs:+4:13: +4:17
40-
- _6 = _3; // scope 0 at $DIR/cycle.rs:+4:20: +4:21
41-
+ nop; // scope 0 at $DIR/cycle.rs:+4:20: +4:21
40+
_6 = _3; // scope 0 at $DIR/cycle.rs:+4:20: +4:21
4241
StorageLive(_7); // scope 1 at $DIR/cycle.rs:+5:13: +5:14
43-
- _7 = _2; // scope 1 at $DIR/cycle.rs:+5:13: +5:14
44-
- _3 = move _7; // scope 1 at $DIR/cycle.rs:+5:9: +5:14
45-
+ nop; // scope 1 at $DIR/cycle.rs:+5:13: +5:14
46-
+ nop; // scope 1 at $DIR/cycle.rs:+5:9: +5:14
42+
_7 = _2; // scope 1 at $DIR/cycle.rs:+5:13: +5:14
43+
_3 = move _7; // scope 1 at $DIR/cycle.rs:+5:9: +5:14
4744
StorageDead(_7); // scope 1 at $DIR/cycle.rs:+5:13: +5:14
4845
StorageLive(_8); // scope 1 at $DIR/cycle.rs:+6:13: +6:14
49-
- _8 = _1; // scope 1 at $DIR/cycle.rs:+6:13: +6:14
50-
- _2 = move _8; // scope 1 at $DIR/cycle.rs:+6:9: +6:14
51-
+ nop; // scope 1 at $DIR/cycle.rs:+6:13: +6:14
52-
+ nop; // scope 1 at $DIR/cycle.rs:+6:9: +6:14
46+
_8 = _1; // scope 1 at $DIR/cycle.rs:+6:13: +6:14
47+
_2 = move _8; // scope 1 at $DIR/cycle.rs:+6:9: +6:14
5348
StorageDead(_8); // scope 1 at $DIR/cycle.rs:+6:13: +6:14
5449
StorageLive(_9); // scope 1 at $DIR/cycle.rs:+7:13: +7:17
55-
- _9 = _6; // scope 1 at $DIR/cycle.rs:+7:13: +7:17
56-
- _1 = move _9; // scope 1 at $DIR/cycle.rs:+7:9: +7:17
57-
+ nop; // scope 1 at $DIR/cycle.rs:+7:13: +7:17
58-
+ nop; // scope 1 at $DIR/cycle.rs:+7:9: +7:17
50+
_9 = _6; // scope 1 at $DIR/cycle.rs:+7:13: +7:17
51+
_1 = move _9; // scope 1 at $DIR/cycle.rs:+7:9: +7:17
5952
StorageDead(_9); // scope 1 at $DIR/cycle.rs:+7:16: +7:17
6053
- _4 = const (); // scope 0 at $DIR/cycle.rs:+3:18: +8:6
6154
+ nop; // scope 0 at $DIR/cycle.rs:+3:18: +8:6

0 commit comments

Comments
 (0)