Skip to content

Commit 571412f

Browse files
committed
mir-opt: Eliminate dead ref statements
1 parent 42b384e commit 571412f

File tree

69 files changed

+2139
-511
lines changed

Some content is hidden

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

69 files changed

+2139
-511
lines changed

compiler/rustc_codegen_ssa/src/mir/analyze.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> Visitor<'tcx> for LocalAnalyzer
260260
PlaceContext::MutatingUse(MutatingUseContext::Yield) => bug!(),
261261
}
262262
}
263+
264+
fn visit_statement_debuginfo(&mut self, _: &mir::StmtDebugInfo<'tcx>, _: Location) {
265+
// Debuginfo does not generate actual code.
266+
}
263267
}
264268

265269
#[derive(Copy, Clone, Debug, PartialEq, Eq)]

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,10 @@ pub struct BasicBlockData<'tcx> {
12981298
/// List of statements in this block.
12991299
pub statements: Vec<Statement<'tcx>>,
13001300

1301+
/// All debuginfos happen before the statement.
1302+
/// Put debuginfos here when the last statement is eliminated.
1303+
pub after_last_stmt_debuginfos: StmtDebugInfos<'tcx>,
1304+
13011305
/// Terminator for this block.
13021306
///
13031307
/// N.B., this should generally ONLY be `None` during construction.
@@ -1325,7 +1329,12 @@ impl<'tcx> BasicBlockData<'tcx> {
13251329
terminator: Option<Terminator<'tcx>>,
13261330
is_cleanup: bool,
13271331
) -> BasicBlockData<'tcx> {
1328-
BasicBlockData { statements, terminator, is_cleanup }
1332+
BasicBlockData {
1333+
statements,
1334+
after_last_stmt_debuginfos: StmtDebugInfos::default(),
1335+
terminator,
1336+
is_cleanup,
1337+
}
13291338
}
13301339

13311340
/// Accessor for terminator.
@@ -1360,6 +1369,36 @@ impl<'tcx> BasicBlockData<'tcx> {
13601369
self.terminator().successors()
13611370
}
13621371
}
1372+
1373+
pub fn retain_statements<F>(&mut self, mut f: F)
1374+
where
1375+
F: FnMut(&Statement<'tcx>) -> bool,
1376+
{
1377+
// Place debuginfos into the next retained statement,
1378+
// this `debuginfos` variable is used to cache debuginfos between two retained statements.
1379+
let mut debuginfos = StmtDebugInfos::default();
1380+
self.statements.retain_mut(|stmt| {
1381+
let retain = f(stmt);
1382+
if retain {
1383+
stmt.debuginfos.prepend(&mut debuginfos);
1384+
} else {
1385+
debuginfos.append(&mut stmt.debuginfos);
1386+
}
1387+
retain
1388+
});
1389+
self.after_last_stmt_debuginfos.prepend(&mut debuginfos);
1390+
}
1391+
1392+
pub fn strip_nops(&mut self) {
1393+
self.retain_statements(|stmt| !matches!(stmt.kind, StatementKind::Nop))
1394+
}
1395+
1396+
pub fn drop_debuginfo(&mut self) {
1397+
self.after_last_stmt_debuginfos.drop_debuginfo();
1398+
for stmt in self.statements.iter_mut() {
1399+
stmt.debuginfos.drop_debuginfo();
1400+
}
1401+
}
13631402
}
13641403

13651404
///////////////////////////////////////////////////////////////////////////
@@ -1664,10 +1703,10 @@ mod size_asserts {
16641703

16651704
use super::*;
16661705
// tidy-alphabetical-start
1667-
static_assert_size!(BasicBlockData<'_>, 128);
1706+
static_assert_size!(BasicBlockData<'_>, 152);
16681707
static_assert_size!(LocalDecl<'_>, 40);
16691708
static_assert_size!(SourceScopeData<'_>, 64);
1670-
static_assert_size!(Statement<'_>, 32);
1709+
static_assert_size!(Statement<'_>, 56);
16711710
static_assert_size!(Terminator<'_>, 96);
16721711
static_assert_size!(VarDebugInfo<'_>, 88);
16731712
// tidy-alphabetical-end

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,11 @@ impl<'de, 'tcx> MirWriter<'de, 'tcx> {
719719
let mut current_location = Location { block, statement_index: 0 };
720720
for statement in &data.statements {
721721
(self.extra_data)(PassWhere::BeforeLocation(current_location), w)?;
722+
723+
for debuginfo in statement.debuginfos.iter() {
724+
writeln!(w, "{INDENT}{INDENT}// DBG: {debuginfo:?};")?;
725+
}
726+
722727
let indented_body = format!("{INDENT}{INDENT}{statement:?};");
723728
if self.options.include_extra_comments {
724729
writeln!(
@@ -749,6 +754,10 @@ impl<'de, 'tcx> MirWriter<'de, 'tcx> {
749754
current_location.statement_index += 1;
750755
}
751756

757+
for debuginfo in data.after_last_stmt_debuginfos.iter() {
758+
writeln!(w, "{INDENT}{INDENT}// DBG: {debuginfo:?};")?;
759+
}
760+
752761
// Terminator at the bottom.
753762
(self.extra_data)(PassWhere::BeforeLocation(current_location), w)?;
754763
if data.terminator.is_some() {
@@ -829,6 +838,16 @@ impl Debug for Statement<'_> {
829838
}
830839
}
831840

841+
impl Debug for StmtDebugInfo<'_> {
842+
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
843+
match self {
844+
StmtDebugInfo::AssignRef(local, place) => {
845+
write!(fmt, "{local:?} = &{place:?}")
846+
}
847+
}
848+
}
849+
}
850+
832851
impl Display for NonDivergingIntrinsic<'_> {
833852
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
834853
match self {

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Functionality for statements, operands, places, and things that appear in them.
22
3+
use std::ops;
4+
35
use tracing::{debug, instrument};
46

57
use super::interpret::GlobalAlloc;
@@ -15,17 +17,34 @@ use crate::ty::CoroutineArgsExt;
1517
pub struct Statement<'tcx> {
1618
pub source_info: SourceInfo,
1719
pub kind: StatementKind<'tcx>,
20+
/// Some debuginfos appearing before the primary statement.
21+
pub debuginfos: StmtDebugInfos<'tcx>,
1822
}
1923

2024
impl<'tcx> Statement<'tcx> {
2125
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
2226
/// invalidating statement indices in `Location`s.
23-
pub fn make_nop(&mut self) {
24-
self.kind = StatementKind::Nop
27+
pub fn make_nop(&mut self, drop_debuginfo: bool) {
28+
if matches!(self.kind, StatementKind::Nop) {
29+
return;
30+
}
31+
let replaced_stmt = std::mem::replace(&mut self.kind, StatementKind::Nop);
32+
if !drop_debuginfo {
33+
match replaced_stmt {
34+
StatementKind::Assign(box (place, Rvalue::Ref(_, _, ref_place)))
35+
if let Some(local) = place.as_local() =>
36+
{
37+
self.debuginfos.push(StmtDebugInfo::AssignRef(local, ref_place));
38+
}
39+
_ => {
40+
bug!("debuginfo is not yet supported.")
41+
}
42+
}
43+
}
2544
}
2645

2746
pub fn new(source_info: SourceInfo, kind: StatementKind<'tcx>) -> Self {
28-
Statement { source_info, kind }
47+
Statement { source_info, kind, debuginfos: StmtDebugInfos::default() }
2948
}
3049
}
3150

@@ -63,6 +82,17 @@ impl<'tcx> StatementKind<'tcx> {
6382
_ => None,
6483
}
6584
}
85+
86+
pub fn as_debuginfo(&self) -> Option<StmtDebugInfo<'tcx>> {
87+
match self {
88+
StatementKind::Assign(box (place, Rvalue::Ref(_, _, ref_place)))
89+
if let Some(local) = place.as_local() =>
90+
{
91+
Some(StmtDebugInfo::AssignRef(local, *ref_place))
92+
}
93+
_ => None,
94+
}
95+
}
6696
}
6797

6898
///////////////////////////////////////////////////////////////////////////
@@ -967,3 +997,70 @@ impl RawPtrKind {
967997
}
968998
}
969999
}
1000+
1001+
#[derive(Default, Debug, Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1002+
pub struct StmtDebugInfos<'tcx>(Vec<StmtDebugInfo<'tcx>>);
1003+
1004+
impl<'tcx> StmtDebugInfos<'tcx> {
1005+
pub fn push(&mut self, debuginfo: StmtDebugInfo<'tcx>) {
1006+
self.0.push(debuginfo);
1007+
}
1008+
1009+
pub fn drop_debuginfo(&mut self) {
1010+
self.0.clear();
1011+
}
1012+
1013+
pub fn is_empty(&self) -> bool {
1014+
self.0.is_empty()
1015+
}
1016+
1017+
pub fn prepend(&mut self, debuginfos: &mut Self) {
1018+
if debuginfos.is_empty() {
1019+
return;
1020+
};
1021+
debuginfos.0.append(self);
1022+
std::mem::swap(debuginfos, self);
1023+
}
1024+
1025+
pub fn append(&mut self, debuginfos: &mut Self) {
1026+
if debuginfos.is_empty() {
1027+
return;
1028+
};
1029+
self.0.append(debuginfos);
1030+
}
1031+
1032+
pub fn extend(&mut self, debuginfos: &Self) {
1033+
if debuginfos.is_empty() {
1034+
return;
1035+
};
1036+
self.0.extend_from_slice(debuginfos);
1037+
}
1038+
1039+
pub fn retain<F>(&mut self, f: F)
1040+
where
1041+
F: FnMut(&StmtDebugInfo<'tcx>) -> bool,
1042+
{
1043+
self.0.retain(f);
1044+
}
1045+
}
1046+
1047+
impl<'tcx> ops::Deref for StmtDebugInfos<'tcx> {
1048+
type Target = Vec<StmtDebugInfo<'tcx>>;
1049+
1050+
#[inline]
1051+
fn deref(&self) -> &Vec<StmtDebugInfo<'tcx>> {
1052+
&self.0
1053+
}
1054+
}
1055+
1056+
impl<'tcx> ops::DerefMut for StmtDebugInfos<'tcx> {
1057+
#[inline]
1058+
fn deref_mut(&mut self) -> &mut Vec<StmtDebugInfo<'tcx>> {
1059+
&mut self.0
1060+
}
1061+
}
1062+
1063+
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
1064+
pub enum StmtDebugInfo<'tcx> {
1065+
AssignRef(Local, Place<'tcx>),
1066+
}

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ macro_rules! make_mir_visitor {
9595
self.super_source_scope_data(scope_data);
9696
}
9797

98+
fn visit_statement_debuginfo(
99+
&mut self,
100+
stmt_debuginfo: & $($mutability)? StmtDebugInfo<'tcx>,
101+
location: Location
102+
) {
103+
self.super_statement_debuginfo(stmt_debuginfo, location);
104+
}
105+
98106
fn visit_statement(
99107
&mut self,
100108
statement: & $($mutability)? Statement<'tcx>,
@@ -301,6 +309,7 @@ macro_rules! make_mir_visitor {
301309
{
302310
let BasicBlockData {
303311
statements,
312+
after_last_stmt_debuginfos,
304313
terminator,
305314
is_cleanup: _
306315
} = data;
@@ -312,8 +321,11 @@ macro_rules! make_mir_visitor {
312321
index += 1;
313322
}
314323

324+
let location = Location { block, statement_index: index };
325+
for debuginfo in after_last_stmt_debuginfos as & $($mutability)? [_] {
326+
self.visit_statement_debuginfo(debuginfo, location);
327+
}
315328
if let Some(terminator) = terminator {
316-
let location = Location { block, statement_index: index };
317329
self.visit_terminator(terminator, location);
318330
}
319331
}
@@ -376,14 +388,38 @@ macro_rules! make_mir_visitor {
376388
}
377389
}
378390

391+
fn super_statement_debuginfo(
392+
&mut self,
393+
stmt_debuginfo: & $($mutability)? StmtDebugInfo<'tcx>,
394+
location: Location
395+
) {
396+
match stmt_debuginfo {
397+
StmtDebugInfo::AssignRef(local, place) => {
398+
self.visit_local(
399+
$(& $mutability)? *local,
400+
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
401+
location
402+
);
403+
self.visit_place(
404+
place,
405+
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
406+
location
407+
);
408+
},
409+
}
410+
}
411+
379412
fn super_statement(
380413
&mut self,
381414
statement: & $($mutability)? Statement<'tcx>,
382415
location: Location
383416
) {
384-
let Statement { source_info, kind } = statement;
417+
let Statement { source_info, kind, debuginfos } = statement;
385418

386419
self.visit_source_info(source_info);
420+
for debuginfo in debuginfos as & $($mutability)? [_] {
421+
self.visit_statement_debuginfo(debuginfo, location);
422+
}
387423
match kind {
388424
StatementKind::Assign(box (place, rvalue)) => {
389425
self.visit_assign(place, rvalue, location);

compiler/rustc_mir_dataflow/src/debuginfo.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ use rustc_middle::mir::*;
55
/// Return the set of locals that appear in debuginfo.
66
pub fn debuginfo_locals(body: &Body<'_>) -> DenseBitSet<Local> {
77
let mut visitor = DebuginfoLocals(DenseBitSet::new_empty(body.local_decls.len()));
8-
for debuginfo in body.var_debug_info.iter() {
9-
visitor.visit_var_debug_info(debuginfo);
10-
}
8+
visitor.visit_body(body);
119
visitor.0
1210
}
1311

1412
struct DebuginfoLocals(DenseBitSet<Local>);
1513

1614
impl Visitor<'_> for DebuginfoLocals {
17-
fn visit_local(&mut self, local: Local, _: PlaceContext, _: Location) {
18-
self.0.insert(local);
15+
fn visit_local(&mut self, local: Local, place_context: PlaceContext, _: Location) {
16+
if place_context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
17+
self.0.insert(local);
18+
}
1919
}
2020
}

0 commit comments

Comments
 (0)