Skip to content

Commit 29306a5

Browse files
committed
Merge places for debuginfo.
1 parent 6d6d774 commit 29306a5

File tree

132 files changed

+1318
-1190
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+1318
-1190
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+85-24
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ use smallvec::SmallVec;
102102
use std::borrow::Cow;
103103

104104
use crate::dataflow_const_prop::DummyMachine;
105+
use crate::simplify::UsedLocals;
105106
use crate::ssa::{AssignedValue, SsaLocals};
106107
use either::Either;
107108

@@ -163,14 +164,16 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
163164
state.next_opaque = None;
164165

165166
let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec();
166-
for dbg in body.var_debug_info.iter_mut() {
167-
state.visit_var_debug_info(dbg);
168-
}
169167
for bb in reverse_postorder {
170168
let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
171169
state.visit_basic_block_data(bb, data);
172170
}
173171

172+
let mut used_locals = UsedLocals::new(body, false);
173+
for dbg in body.var_debug_info.iter_mut() {
174+
state.reduce_debuginfo(dbg, &mut used_locals);
175+
}
176+
174177
// For each local that is reused (`y` above), we remove its storage statements do avoid any
175178
// difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage
176179
// statements.
@@ -1256,45 +1259,93 @@ impl<'tcx> VnState<'_, 'tcx> {
12561259
.find(|&&other| self.ssa.assignment_dominates(self.dominators, other, loc))
12571260
.copied()
12581261
}
1259-
}
1260-
1261-
impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1262-
fn tcx(&self) -> TyCtxt<'tcx> {
1263-
self.tcx
1264-
}
1265-
1266-
fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) {
1267-
let mut replace_dereffed = |place: &mut Place<'tcx>| -> Option<!> {
1268-
let last_deref = place.projection.iter().rposition(|e| e == PlaceElem::Deref)?;
12691262

1270-
// Another place that holds the same value.
1263+
fn reduce_debuginfo(
1264+
&mut self,
1265+
var_debug_info: &mut VarDebugInfo<'tcx>,
1266+
used_locals: &mut UsedLocals,
1267+
) {
1268+
let mut simplify_place = |place: &mut Place<'tcx>| -> Option<ConstOperand<'tcx>> {
1269+
// Another place that points to the same memory.
12711270
let mut place_ref = place.as_ref();
12721271
let mut value = self.locals[place.local]?;
12731272

1274-
for (index, &proj) in place.projection[..last_deref].iter().enumerate() {
1275-
if let Some(candidates) = self.rev_locals.get(value)
1276-
&& let Some(&local) = candidates.first()
1273+
// The position of the last deref projection. If there is one, the place preceding it
1274+
// can be treated and simplified as a value. Afterwards, projections need to be treated
1275+
// as a memory place.
1276+
let last_deref = place.projection.iter().rposition(|e| e == PlaceElem::Deref);
1277+
1278+
for (index, proj) in place.projection.iter().enumerate() {
1279+
// We are before the last projection, so we can treat as a value.
1280+
if last_deref.map_or(false, |ld| index <= ld)
1281+
&& let Some(candidates) = self.rev_locals.get(value)
1282+
// Do not introduce an unused local.
1283+
&& let Some(&local) = candidates.iter().find(|&&l| used_locals.is_used(l))
12771284
{
12781285
place_ref = PlaceRef { local, projection: &place.projection[index..] };
12791286
}
12801287

1288+
// We are at the last projection, treat as a value if possible.
1289+
if Some(index) == last_deref {
1290+
*place = place_ref.project_deeper(&[], self.tcx);
1291+
1292+
// If the base local is used, do not bother trying to simplify anything.
1293+
if used_locals.is_used(place_ref.local) {
1294+
return None;
1295+
}
1296+
}
1297+
12811298
let place_upto =
12821299
PlaceRef { local: place.local, projection: &place.projection[..index] };
12831300
if let Some(projected) = self.project(place_upto, value, proj) {
12841301
value = projected;
12851302
} else {
1286-
if place_ref.projection.len() < place.projection.len() {
1303+
if last_deref.map_or(false, |ld| index <= ld)
1304+
&& place_ref.projection.len() < place.projection.len()
1305+
{
12871306
*place = place_ref.project_deeper(&[], self.tcx);
12881307
}
12891308
return None;
12901309
}
12911310
}
12921311

1293-
if let Some(candidates) = self.rev_locals.get(value)
1294-
&& let Some(&local) = candidates.first()
1295-
{
1296-
let place_ref = PlaceRef { local, projection: &place.projection[last_deref..] };
1297-
*place = place_ref.project_deeper(&[], self.tcx);
1312+
if let Some(constant) = self.try_as_constant(value) {
1313+
return Some(constant);
1314+
}
1315+
1316+
let mut projections = vec![];
1317+
loop {
1318+
if let Some(candidates) = self.rev_locals.get(value)
1319+
// Do not reintroduce an unused local.
1320+
&& let Some(&local) = candidates.iter().find(|&&l| used_locals.is_used(l))
1321+
{
1322+
projections.reverse();
1323+
*place = Place {
1324+
local,
1325+
projection: self.tcx.mk_place_elems_from_iter(projections.into_iter()),
1326+
};
1327+
return None;
1328+
}
1329+
1330+
let Value::Projection(base, elem) = *self.get(value) else {
1331+
break;
1332+
};
1333+
1334+
let elem = match elem {
1335+
ProjectionElem::Deref => ProjectionElem::Deref,
1336+
ProjectionElem::Downcast(name, read_variant) => {
1337+
ProjectionElem::Downcast(name, read_variant)
1338+
}
1339+
ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty),
1340+
ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => {
1341+
ProjectionElem::ConstantIndex { offset, min_length, from_end: false }
1342+
}
1343+
// Not allowed in debuginfo.
1344+
_ => return None,
1345+
};
1346+
1347+
projections.push(elem);
1348+
value = base;
12981349
}
12991350

13001351
return None;
@@ -1303,10 +1354,20 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
13031354
match &mut var_debug_info.value {
13041355
VarDebugInfoContents::Const(_) => {}
13051356
VarDebugInfoContents::Place(place) => {
1306-
replace_dereffed(place);
1357+
if let Some(constant) = simplify_place(place) {
1358+
var_debug_info.value = VarDebugInfoContents::Const(constant);
1359+
} else {
1360+
used_locals.use_count[place.local] += 1;
1361+
}
13071362
}
13081363
}
13091364
}
1365+
}
1366+
1367+
impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1368+
fn tcx(&self) -> TyCtxt<'tcx> {
1369+
self.tcx
1370+
}
13101371

13111372
fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, location: Location) {
13121373
self.simplify_place_projection(place, location);

compiler/rustc_mir_transform/src/simplify.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
//! return.
2929
3030
use rustc_index::{Idx, IndexSlice, IndexVec};
31-
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
31+
use rustc_middle::mir::visit::{
32+
MutVisitor, MutatingUseContext, NonUseContext, PlaceContext, Visitor,
33+
};
3234
use rustc_middle::mir::*;
3335
use rustc_middle::ty::TyCtxt;
3436
use smallvec::SmallVec;
@@ -382,7 +384,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {
382384

383385
pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
384386
// First, we're going to get a count of *actual* uses for every `Local`.
385-
let mut used_locals = UsedLocals::new(body);
387+
let mut used_locals = UsedLocals::new(body, true);
386388

387389
// Next, we're going to remove any `Local` with zero actual uses. When we remove those
388390
// `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
@@ -394,7 +396,7 @@ pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
394396

395397
pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
396398
// First, we're going to get a count of *actual* uses for every `Local`.
397-
let mut used_locals = UsedLocals::new(body);
399+
let mut used_locals = UsedLocals::new(body, true);
398400

399401
// Next, we're going to remove any `Local` with zero actual uses. When we remove those
400402
// `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
@@ -441,19 +443,21 @@ fn make_local_map<V>(
441443
}
442444

443445
/// Keeps track of used & unused locals.
444-
struct UsedLocals {
446+
pub(crate) struct UsedLocals {
445447
increment: bool,
446448
arg_count: u32,
447-
use_count: IndexVec<Local, u32>,
449+
pub(crate) use_count: IndexVec<Local, u32>,
450+
with_debuginfo: bool,
448451
}
449452

450453
impl UsedLocals {
451454
/// Determines which locals are used & unused in the given body.
452-
fn new(body: &Body<'_>) -> Self {
455+
pub(crate) fn new(body: &Body<'_>, with_debuginfo: bool) -> Self {
453456
let mut this = Self {
454457
increment: true,
455458
arg_count: body.arg_count.try_into().unwrap(),
456459
use_count: IndexVec::from_elem(0, &body.local_decls),
460+
with_debuginfo,
457461
};
458462
this.visit_body(body);
459463
this
@@ -462,7 +466,7 @@ impl UsedLocals {
462466
/// Checks if local is used.
463467
///
464468
/// Return place and arguments are always considered used.
465-
fn is_used(&self, local: Local) -> bool {
469+
pub(crate) fn is_used(&self, local: Local) -> bool {
466470
trace!("is_used({:?}): use_count: {:?}", local, self.use_count[local]);
467471
local.as_u32() <= self.arg_count || self.use_count[local] != 0
468472
}
@@ -526,7 +530,11 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
526530
}
527531
}
528532

529-
fn visit_local(&mut self, local: Local, _ctx: PlaceContext, _location: Location) {
533+
fn visit_local(&mut self, local: Local, ctx: PlaceContext, _location: Location) {
534+
if matches!(ctx, PlaceContext::NonUse(NonUseContext::VarDebugInfo)) && !self.with_debuginfo
535+
{
536+
return;
537+
};
530538
if self.increment {
531539
self.use_count[local] += 1;
532540
} else {

tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff

+7-14
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,16 @@
1111
let mut _14: u32;
1212
let mut _15: u32;
1313
scope 1 {
14-
- debug x => _1;
15-
+ debug x => const 1_u8;
14+
debug x => const 1_u8;
1615
let _2: u8;
1716
scope 2 {
18-
- debug y => _2;
19-
+ debug y => const 2_u8;
17+
debug y => const 2_u8;
2018
let _3: u8;
2119
scope 3 {
22-
- debug z => _3;
23-
+ debug z => const 3_u8;
20+
debug z => const 3_u8;
2421
let _4: u8;
2522
scope 4 {
26-
- debug sum => _4;
27-
+ debug sum => const 6_u8;
23+
debug sum => const 6_u8;
2824
let _9: &str;
2925
scope 5 {
3026
- debug s => _9;
@@ -34,16 +30,13 @@
3430
debug f => _10;
3531
let _11: std::option::Option<u16>;
3632
scope 7 {
37-
- debug o => _11;
38-
+ debug o => const Option::<u16>::Some(99_u16);
33+
debug o => const Option::<u16>::Some(99_u16);
3934
let _12: Point;
4035
scope 8 {
41-
- debug p => _12;
42-
+ debug p => const Point {{ x: 32_u32, y: 32_u32 }};
36+
debug p => const Point {{ x: 32_u32, y: 32_u32 }};
4337
let _13: u32;
4438
scope 9 {
45-
- debug a => _13;
46-
+ debug a => const 64_u32;
39+
debug a => const 64_u32;
4740
}
4841
}
4942
}

tests/mir-opt/const_prop/aggregate.foo.GVN.panic-abort.diff

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
let mut _8: (u8, i32);
1313
let mut _9: u8;
1414
scope 1 {
15-
debug first => _2;
15+
- debug first => _2;
16+
+ debug first => const 1_i32;
1617
let _6: i32;
1718
scope 2 {
18-
debug second => _6;
19+
- debug second => _6;
20+
+ debug second => const 3_i32;
1921
}
2022
}
2123

tests/mir-opt/const_prop/aggregate.foo.GVN.panic-unwind.diff

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
let mut _8: (u8, i32);
1313
let mut _9: u8;
1414
scope 1 {
15-
debug first => _2;
15+
- debug first => _2;
16+
+ debug first => const 1_i32;
1617
let _6: i32;
1718
scope 2 {
18-
debug second => _6;
19+
- debug second => _6;
20+
+ debug second => const 3_i32;
1921
}
2022
}
2123

tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
let _4: ();
1010
let mut _5: u8;
1111
scope 1 {
12-
debug x => _1;
12+
- debug x => _1;
13+
+ debug x => const 1_u8;
1314
}
1415

1516
bb0: {

tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
let _4: ();
1010
let mut _5: u8;
1111
scope 1 {
12-
debug x => _1;
12+
- debug x => _1;
13+
+ debug x => const 1_u8;
1314
}
1415

1516
bb0: {

tests/mir-opt/const_prop/aggregate.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
// EMIT_MIR aggregate.main.GVN.diff
66
fn main() {
77
// CHECK-LABEL: fn main(
8-
// CHECK: debug x => [[x:_.*]];
9-
// CHECK-NOT: = Add(
10-
// CHECK: [[x]] = const 1_u8;
8+
// CHECK: debug x => const 1_u8;
119
// CHECK-NOT: = Add(
1210
// CHECK: foo(const 1_u8)
1311
let x = (0, 1, 2).1 + 0;
@@ -18,12 +16,9 @@ fn main() {
1816
// EMIT_MIR aggregate.foo.GVN.diff
1917
fn foo(x: u8) {
2018
// CHECK-LABEL: fn foo(
21-
// CHECK: debug first => [[first:_.*]];
22-
// CHECK: debug second => [[second:_.*]];
23-
// CHECK-NOT: = Add(
24-
// CHECK: [[first]] = const 1_i32;
19+
// CHECK: debug first => const 1_i32;
20+
// CHECK: debug second => const 3_i32;
2521
// CHECK-NOT: = Add(
26-
// CHECK: [[second]] = const 3_i32;
2722
let first = (0, x).0 + 1;
2823
let second = (x, 1).1 + 2;
2924
}

tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
let mut _4: usize;
1010
let mut _5: bool;
1111
scope 1 {
12-
debug x => _1;
12+
- debug x => _1;
13+
+ debug x => const 2_u32;
1314
}
1415

1516
bb0: {

tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
let mut _4: usize;
1010
let mut _5: bool;
1111
scope 1 {
12-
debug x => _1;
12+
- debug x => _1;
13+
+ debug x => const 2_u32;
1314
}
1415

1516
bb0: {

tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
let mut _4: usize;
1010
let mut _5: bool;
1111
scope 1 {
12-
debug x => _1;
12+
- debug x => _1;
13+
+ debug x => const 2_u32;
1314
}
1415

1516
bb0: {

0 commit comments

Comments
 (0)