Skip to content

Commit 27d6a57

Browse files
committed
Preserve DebugInfo in DeadStoreElimination.
1 parent 1bc0463 commit 27d6a57

File tree

30 files changed

+764
-798
lines changed

30 files changed

+764
-798
lines changed

compiler/rustc_index/src/bit_set.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ impl<T: Idx> From<GrowableBitSet<T>> for BitSet<T> {
365365
/// All operations that involve an element will panic if the element is equal
366366
/// to or greater than the domain size. All operations that involve two bitsets
367367
/// will panic if the bitsets have differing domain sizes.
368-
#[derive(Debug, PartialEq, Eq)]
368+
#[derive(PartialEq, Eq)]
369369
pub struct ChunkedBitSet<T> {
370370
domain_size: usize,
371371

@@ -1074,6 +1074,12 @@ impl<T: Idx> fmt::Debug for BitSet<T> {
10741074
}
10751075
}
10761076

1077+
impl<T: Idx> fmt::Debug for ChunkedBitSet<T> {
1078+
fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
1079+
w.debug_list().entries(self.iter()).finish()
1080+
}
1081+
}
1082+
10771083
impl<T: Idx> ToString for BitSet<T> {
10781084
fn to_string(&self) -> String {
10791085
let mut result = String::new();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use rustc_index::bit_set::BitSet;
2+
use rustc_middle::mir::visit::*;
3+
use rustc_middle::mir::*;
4+
5+
/// Return the set of locals that appear in debuginfo.
6+
pub fn debuginfo_locals(body: &Body<'_>) -> BitSet<Local> {
7+
let mut visitor = DebuginfoLocals(BitSet::new_empty(body.local_decls.len()));
8+
for debuginfo in body.var_debug_info.iter() {
9+
visitor.visit_var_debug_info(debuginfo);
10+
}
11+
visitor.0
12+
}
13+
14+
struct DebuginfoLocals(BitSet<Local>);
15+
16+
impl Visitor<'_> for DebuginfoLocals {
17+
fn visit_local(&mut self, local: Local, _: PlaceContext, _: Location) {
18+
self.0.insert(local);
19+
}
20+
}

compiler/rustc_mir_dataflow/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub use self::framework::{
3535

3636
use self::move_paths::MoveData;
3737

38+
pub mod debuginfo;
3839
pub mod drop_flag_effects;
3940
pub mod elaborate_drops;
4041
mod errors;

compiler/rustc_mir_transform/src/dead_store_elimination.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
//!
1414
1515
use crate::util::is_within_packed;
16-
use rustc_index::bit_set::BitSet;
1716
use rustc_middle::mir::visit::Visitor;
1817
use rustc_middle::mir::*;
1918
use rustc_middle::ty::TyCtxt;
19+
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
2020
use rustc_mir_dataflow::impls::{
2121
borrowed_locals, LivenessTransferFunction, MaybeTransitiveLiveLocals,
2222
};
@@ -26,8 +26,15 @@ use rustc_mir_dataflow::Analysis;
2626
///
2727
/// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
2828
/// can be generated via the [`borrowed_locals`] function.
29-
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
30-
let mut live = MaybeTransitiveLiveLocals::new(borrowed)
29+
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
30+
let borrowed_locals = borrowed_locals(body);
31+
32+
// If the user requests complete debuginfo, mark the locals that appear in it as live, so
33+
// we don't remove assignements to them.
34+
let mut always_live = debuginfo_locals(body);
35+
always_live.union(&borrowed_locals);
36+
37+
let mut live = MaybeTransitiveLiveLocals::new(&always_live)
3138
.into_engine(tcx, body)
3239
.iterate_to_fixpoint()
3340
.into_results_cursor(body);
@@ -48,7 +55,9 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
4855
for (index, arg) in args.iter().enumerate().rev() {
4956
if let Operand::Copy(place) = *arg
5057
&& !place.is_indirect()
51-
&& !borrowed.contains(place.local)
58+
// Do not skip the transformation if the local is in debuginfo, as we do
59+
// not really lose any information for this purpose.
60+
&& !borrowed_locals.contains(place.local)
5261
&& !state.contains(place.local)
5362
// If `place` is a projection of a disaligned field in a packed ADT,
5463
// the move may be codegened as a pointer to that field.
@@ -75,7 +84,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
7584
StatementKind::Assign(box (place, _))
7685
| StatementKind::SetDiscriminant { place: box place, .. }
7786
| StatementKind::Deinit(box place) => {
78-
if !place.is_indirect() && !borrowed.contains(place.local) {
87+
if !place.is_indirect() && !always_live.contains(place.local) {
7988
live.seek_before_primary_effect(loc);
8089
if !live.get().contains(place.local) {
8190
patch.push(loc);
@@ -126,7 +135,6 @@ impl<'tcx> MirPass<'tcx> for DeadStoreElimination {
126135
}
127136

128137
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
129-
let borrowed = borrowed_locals(body);
130-
eliminate(tcx, body, &borrowed);
138+
eliminate(tcx, body);
131139
}
132140
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
- // MIR for `cycle` before DeadStoreElimination
2+
+ // MIR for `cycle` after DeadStoreElimination
3+
4+
fn cycle(_1: i32, _2: i32, _3: i32) -> () {
5+
let mut _0: ();
6+
let mut _4: bool;
7+
- let mut _5: i32;
8+
9+
bb0: {
10+
_4 = cond() -> [return: bb1, unwind continue];
11+
}
12+
13+
bb1: {
14+
switchInt(_4) -> [1: bb2, otherwise: bb3];
15+
}
16+
17+
bb2: {
18+
- _5 = _3;
19+
- _3 = _2;
20+
- _2 = _1;
21+
- _1 = _5;
22+
_4 = cond() -> [return: bb1, unwind continue];
23+
}
24+
25+
bb3: {
26+
return;
27+
}
28+
}
29+

tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-abort.diff

-73
This file was deleted.

tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.panic-unwind.diff

-73
This file was deleted.

tests/mir-opt/dead-store-elimination/cycle.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
1-
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
1+
// This example is interesting because the non-transitive version of `MaybeLiveLocals` would
2+
// report that *all* of these stores are live.
3+
//
4+
// needs-unwind
25
// unit-test: DeadStoreElimination
36

7+
#![feature(core_intrinsics, custom_mir)]
8+
use std::intrinsics::mir::*;
9+
410
#[inline(never)]
511
fn cond() -> bool {
612
false
713
}
814

915
// EMIT_MIR cycle.cycle.DeadStoreElimination.diff
16+
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
1017
fn cycle(mut x: i32, mut y: i32, mut z: i32) {
11-
// This example is interesting because the non-transitive version of `MaybeLiveLocals` would
12-
// report that *all* of these stores are live.
13-
while cond() {
14-
let temp = z;
15-
z = y;
16-
y = x;
17-
x = temp;
18-
}
18+
// We use custom MIR to avoid generating debuginfo, that would force to preserve writes.
19+
mir!(
20+
let condition: bool;
21+
{
22+
Call(condition = cond(), bb1)
23+
}
24+
bb1 = {
25+
match condition { true => bb2, _ => ret }
26+
}
27+
bb2 = {
28+
let temp = z;
29+
z = y;
30+
y = x;
31+
x = temp;
32+
Call(condition = cond(), bb1)
33+
}
34+
ret = {
35+
Return()
36+
}
37+
)
1938
}
2039

2140
fn main() {

tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-abort.mir

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@ fn f(_1: usize) -> usize {
77
let mut _3: usize;
88
let mut _4: usize;
99
scope 1 {
10-
debug b => _1;
10+
debug b => _3;
1111
}
1212

1313
bb0: {
1414
nop;
15+
_3 = _1;
16+
_1 = const 5_usize;
1517
nop;
1618
nop;
17-
nop;
18-
nop;
19+
_1 = move _3;
1920
nop;
2021
nop;
2122
nop;

tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.panic-unwind.mir

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@ fn f(_1: usize) -> usize {
77
let mut _3: usize;
88
let mut _4: usize;
99
scope 1 {
10-
debug b => _1;
10+
debug b => _3;
1111
}
1212

1313
bb0: {
1414
nop;
15+
_3 = _1;
16+
_1 = const 5_usize;
1517
nop;
1618
nop;
17-
nop;
18-
nop;
19+
_1 = move _3;
1920
nop;
2021
nop;
2122
nop;

tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff

+2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
}
2323

2424
bb1: {
25+
_1 = Un { us: move _2 };
2526
StorageDead(_2);
2627
StorageLive(_3);
28+
_3 = (_1.0: u32);
2729
StorageDead(_3);
2830
StorageDead(_1);
2931
return;

tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff

+2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
}
2323

2424
bb1: {
25+
_1 = Un { us: move _2 };
2526
StorageDead(_2);
2627
StorageLive(_3);
28+
_3 = (_1.0: u32);
2729
StorageDead(_3);
2830
StorageDead(_1);
2931
return;

0 commit comments

Comments
 (0)