Skip to content

Commit c6220a4

Browse files
committed
mir-opt: Eliminate statements need debuginfo when mir-opt-level >= 2
`-Copt-level=0` (`-Zmir-opt-level=1`) is preferred for debugging.
1 parent 66a8e4d commit c6220a4

File tree

38 files changed

+319
-379
lines changed

38 files changed

+319
-379
lines changed

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,13 @@ impl<'tcx> BasicBlockData<'tcx> {
14331433
pub fn strip_nops(&mut self) {
14341434
self.retain_statements(|stmt| !matches!(stmt.kind, StatementKind::Nop))
14351435
}
1436+
1437+
pub fn drop_debuginfo(&mut self) {
1438+
self.after_last_stmt_debuginfos = Vec::new();
1439+
for stmt in self.statements.iter_mut() {
1440+
stmt.debuginfos = Vec::new();
1441+
}
1442+
}
14361443
}
14371444

14381445
///////////////////////////////////////////////////////////////////////////

compiler/rustc_mir_transform/src/copy_prop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
5252
Replacer { tcx, copy_classes: ssa.copy_classes(), fully_moved, storage_to_remove }
5353
.visit_body_preserves_cfg(body);
5454

55-
crate::simplify::remove_unused_definitions(body);
55+
crate::simplify::remove_unused_definitions(body, tcx.sess.mir_opt_level());
5656
}
5757

5858
fn is_required(&self) -> bool {

compiler/rustc_mir_transform/src/dead_store_elimination.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@ use rustc_mir_dataflow::impls::{
2222
LivenessTransferFunction, MaybeTransitiveLiveLocals, borrowed_locals,
2323
};
2424

25+
use crate::simplify::remove_unused_definitions;
2526
use crate::util::is_within_packed;
2627

2728
/// Performs the optimization on the body
2829
///
2930
/// The `borrowed` set must be a `DenseBitSet` of all the locals that are ever borrowed in this
3031
/// body. It can be generated via the [`borrowed_locals`] function.
31-
fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
32+
fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
3233
let borrowed_locals = borrowed_locals(body);
3334

3435
// If the user requests complete debuginfo, mark the locals that appear in it as live, so
@@ -89,8 +90,9 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
8990
}
9091

9192
if patch.is_empty() && call_operands_to_move.is_empty() {
92-
return;
93+
return false;
9394
}
95+
let eliminated = !patch.is_empty();
9496

9597
let bbs = body.basic_blocks.as_mut_preserves_cfg();
9698
for (Location { block, statement_index }, drop_debuginfo) in patch {
@@ -104,6 +106,8 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
104106
let Operand::Copy(place) = *arg else { bug!() };
105107
*arg = Operand::Move(place);
106108
}
109+
110+
eliminated
107111
}
108112

109113
pub(super) enum DeadStoreElimination {
@@ -124,7 +128,10 @@ impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination {
124128
}
125129

126130
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
127-
eliminate(tcx, body);
131+
if eliminate(tcx, body) {
132+
// Remove unnecessary StorageLive and StorageDead annotations.
133+
remove_unused_definitions(body, tcx.sess.mir_opt_level());
134+
}
128135
}
129136

130137
fn is_required(&self) -> bool {

compiler/rustc_mir_transform/src/inline.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,10 @@ fn inline_call<'tcx, I: Inliner<'tcx>>(
995995
// people working on rust can build with or without debuginfo while
996996
// still getting consistent results from the mir-opt tests.
997997
caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
998+
} else {
999+
for bb in callee_body.basic_blocks_mut() {
1000+
bb.drop_debuginfo();
1001+
}
9981002
}
9991003
caller_body.basic_blocks_mut().append(callee_body.basic_blocks_mut());
10001004

compiler/rustc_mir_transform/src/ref_prop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
9999
replacer.visit_body_preserves_cfg(body);
100100

101101
if replacer.any_replacement {
102-
crate::simplify::remove_unused_definitions(body);
102+
crate::simplify::remove_unused_definitions(body, tcx.sess.mir_opt_level());
103103
}
104104

105105
replacer.any_replacement

compiler/rustc_mir_transform/src/simplify.rs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
423423
// count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
424424
// `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
425425
// fixedpoint where there are no more unused locals.
426-
remove_unused_definitions_helper(&mut used_locals, body);
426+
remove_unused_definitions_helper(&mut used_locals, body, tcx.sess.mir_opt_level());
427427

428428
// Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the
429429
// `Local`s.
@@ -444,7 +444,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
444444
}
445445
}
446446

447-
pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
447+
pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>, mir_opt_level: usize) {
448448
// First, we're going to get a count of *actual* uses for every `Local`.
449449
let mut used_locals = UsedLocals::new(body);
450450

@@ -453,7 +453,7 @@ pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
453453
// count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
454454
// `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
455455
// fixedpoint where there are no more unused locals.
456-
remove_unused_definitions_helper(&mut used_locals, body);
456+
remove_unused_definitions_helper(&mut used_locals, body, mir_opt_level);
457457
}
458458

459459
/// Construct the mapping while swapping out unused stuff out from the `vec`.
@@ -466,7 +466,7 @@ fn make_local_map<V>(
466466

467467
for alive_index in local_decls.indices() {
468468
// `is_used` treats the `RETURN_PLACE` and arguments as used.
469-
if !used_locals.is_used(alive_index) {
469+
if !used_locals.is_used(alive_index, true) {
470470
continue;
471471
}
472472

@@ -504,16 +504,14 @@ impl UsedLocals {
504504
/// Checks if local is used.
505505
///
506506
/// Return place and arguments are always considered used.
507-
fn is_used(&self, local: Local) -> bool {
507+
fn is_used(&self, local: Local, debuginfo_is_used: bool) -> bool {
508508
trace!(
509509
"is_used({:?}): use_count: {:?}, debuginfo_use: {}",
510510
local, self.use_count[local], self.debuginfo_use[local]
511511
);
512-
local.as_u32() <= self.arg_count || self.use_count[local] != 0 || self.debuginfo_use[local]
513-
}
514-
515-
fn is_only_debuginfo_used(&self, local: Local) -> bool {
516-
local.as_u32() > self.arg_count && self.use_count[local] == 0 && self.debuginfo_use[local]
512+
local.as_u32() <= self.arg_count
513+
|| self.use_count[local] != 0
514+
|| (debuginfo_is_used && self.debuginfo_use[local])
517515
}
518516

519517
fn is_debuginfo_used(&self, local: Local) -> bool {
@@ -605,36 +603,46 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
605603
}
606604

607605
/// Removes unused definitions. Updates the used locals to reflect the changes made.
608-
fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Body<'_>) {
606+
fn remove_unused_definitions_helper(
607+
used_locals: &mut UsedLocals,
608+
body: &mut Body<'_>,
609+
mir_opt_level: usize,
610+
) {
609611
// The use counts are updated as we remove the statements. A local might become unused
610612
// during the retain operation, leading to a temporary inconsistency (storage statements or
611613
// definitions referencing the local might remain). For correctness it is crucial that this
612614
// computation reaches a fixed point.
613615

614616
let mut modified = true;
617+
// Transform statements to debug information only when user requests more aggressive optimization.
618+
// This may degrade the debugging experience.
619+
let debuginfo_is_used = mir_opt_level < 2;
615620
while modified {
616621
modified = false;
617622

618623
for data in body.basic_blocks.as_mut_preserves_cfg() {
619624
// Remove unnecessary StorageLive and StorageDead annotations.
620625
for statement in data.statements.iter_mut() {
621626
let (keep_statement, drop_debuginfo) = match &statement.kind {
622-
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => (
623-
!used_locals.is_used(*local) || used_locals.is_only_debuginfo_used(*local),
624-
true,
625-
),
627+
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
628+
(used_locals.is_used(*local, debuginfo_is_used), true)
629+
}
626630
StatementKind::Assign(box (place, _))
627631
| StatementKind::SetDiscriminant { box place, .. }
628632
| StatementKind::BackwardIncompatibleDropHint { box place, .. }
629633
| StatementKind::Deinit(box place) => (
630-
!used_locals.is_used(place.local)
631-
|| (used_locals.is_only_debuginfo_used(place.local)
632-
&& statement.kind.as_debuginfo().is_some()),
634+
used_locals.is_used(
635+
place.local,
636+
debuginfo_is_used
637+
// FIXME: We are not sure how we should represent this debugging information for some statements,
638+
// keep it for now.
639+
|| statement.kind.as_debuginfo().is_none(),
640+
),
633641
!used_locals.is_debuginfo_used(place.local),
634642
),
635643
_ => continue,
636644
};
637-
if !keep_statement {
645+
if keep_statement {
638646
continue;
639647
}
640648
trace!("removing statement {:?}", statement);

tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-abort.diff

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@
2424
bb0: {
2525
- StorageLive(_2);
2626
_2 = &raw mut _1;
27-
- StorageLive(_3);
28-
- StorageLive(_4);
29-
- _4 = &mut (*_2);
30-
- _3 = &mut (*_4);
31-
- StorageDead(_4);
27+
StorageLive(_3);
28+
StorageLive(_4);
29+
_4 = &mut (*_2);
30+
_3 = &mut (*_4);
31+
StorageDead(_4);
3232
- StorageLive(_5);
3333
- _5 = copy _2;
34-
+ // DBG: _4 = &(*_2)
35-
+ // DBG: _3 = &(*_4)
3634
StorageLive(_6);
3735
- StorageLive(_7);
3836
- _7 = copy _5;
@@ -45,7 +43,7 @@
4543
StorageDead(_6);
4644
_0 = const ();
4745
- StorageDead(_5);
48-
- StorageDead(_3);
46+
StorageDead(_3);
4947
- StorageDead(_2);
5048
return;
5149
}

tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.panic-unwind.diff

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@
2424
bb0: {
2525
- StorageLive(_2);
2626
_2 = &raw mut _1;
27-
- StorageLive(_3);
28-
- StorageLive(_4);
29-
- _4 = &mut (*_2);
30-
- _3 = &mut (*_4);
31-
- StorageDead(_4);
27+
StorageLive(_3);
28+
StorageLive(_4);
29+
_4 = &mut (*_2);
30+
_3 = &mut (*_4);
31+
StorageDead(_4);
3232
- StorageLive(_5);
3333
- _5 = copy _2;
34-
+ // DBG: _4 = &(*_2)
35-
+ // DBG: _3 = &(*_4)
3634
StorageLive(_6);
3735
- StorageLive(_7);
3836
- _7 = copy _5;
@@ -45,7 +43,7 @@
4543
StorageDead(_6);
4644
_0 = const ();
4745
- StorageDead(_5);
48-
- StorageDead(_3);
46+
StorageDead(_3);
4947
- StorageDead(_2);
5048
return;
5149
}

tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-abort.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
bb0: {
2424
- StorageLive(_2);
2525
_2 = &raw mut _1;
26-
- StorageLive(_3);
26+
StorageLive(_3);
2727
_3 = &raw mut (*_2);
2828
- StorageLive(_4);
2929
- _4 = copy _2;
@@ -39,7 +39,7 @@
3939
StorageDead(_5);
4040
_0 = const ();
4141
- StorageDead(_4);
42-
- StorageDead(_3);
42+
StorageDead(_3);
4343
- StorageDead(_2);
4444
return;
4545
}

tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.panic-unwind.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
bb0: {
2424
- StorageLive(_2);
2525
_2 = &raw mut _1;
26-
- StorageLive(_3);
26+
StorageLive(_3);
2727
_3 = &raw mut (*_2);
2828
- StorageLive(_4);
2929
- _4 = copy _2;
@@ -39,7 +39,7 @@
3939
StorageDead(_5);
4040
_0 = const ();
4141
- StorageDead(_4);
42-
- StorageDead(_3);
42+
StorageDead(_3);
4343
- StorageDead(_2);
4444
return;
4545
}

0 commit comments

Comments
 (0)