Skip to content

Commit 4fccb1d

Browse files
committed
mir-opt: Allow other passes to use DSE
1 parent f174fd7 commit 4fccb1d

File tree

1 file changed

+59
-36
lines changed

1 file changed

+59
-36
lines changed

compiler/rustc_mir_transform/src/dead_store_elimination.rs

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,71 @@
1212
//! will still not cause any further changes.
1313
//!
1414
15+
use rustc_index::bit_set::DenseBitSet;
1516
use rustc_middle::bug;
1617
use rustc_middle::mir::visit::Visitor;
1718
use rustc_middle::mir::*;
1819
use rustc_middle::ty::TyCtxt;
19-
use rustc_mir_dataflow::Analysis;
2020
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
2121
use rustc_mir_dataflow::impls::{
2222
LivenessTransferFunction, MaybeTransitiveLiveLocals, borrowed_locals,
2323
};
24+
use rustc_mir_dataflow::{Analysis, ResultsCursor};
2425

2526
use crate::util::is_within_packed;
2627

28+
pub(crate) struct DeadStoreAnalysis<'tcx, 'mir, 'a> {
29+
live: ResultsCursor<'mir, 'tcx, MaybeTransitiveLiveLocals<'a>>,
30+
always_live: &'a DenseBitSet<Local>,
31+
}
32+
33+
impl<'tcx, 'mir, 'a> DeadStoreAnalysis<'tcx, 'mir, 'a> {
34+
pub(crate) fn new(
35+
tcx: TyCtxt<'tcx>,
36+
body: &'mir Body<'tcx>,
37+
always_live: &'a DenseBitSet<Local>,
38+
) -> Self {
39+
let live = MaybeTransitiveLiveLocals::new(&always_live)
40+
.iterate_to_fixpoint(tcx, body, None)
41+
.into_results_cursor(body);
42+
Self { live, always_live }
43+
}
44+
45+
pub(crate) fn is_dead_store(&mut self, loc: Location, stmt_kind: &StatementKind<'tcx>) -> bool {
46+
if let StatementKind::Assign(assign) = stmt_kind {
47+
if !assign.1.is_safe_to_remove() {
48+
return false;
49+
}
50+
}
51+
match stmt_kind {
52+
StatementKind::Assign(box (place, _))
53+
| StatementKind::SetDiscriminant { place: box place, .. }
54+
| StatementKind::Deinit(box place) => {
55+
if !place.is_indirect() && !self.always_live.contains(place.local) {
56+
self.live.seek_before_primary_effect(loc);
57+
!self.live.get().contains(place.local)
58+
} else {
59+
false
60+
}
61+
}
62+
63+
StatementKind::Retag(_, _)
64+
| StatementKind::StorageLive(_)
65+
| StatementKind::StorageDead(_)
66+
| StatementKind::Coverage(_)
67+
| StatementKind::Intrinsic(_)
68+
| StatementKind::ConstEvalCounter
69+
| StatementKind::PlaceMention(_)
70+
| StatementKind::BackwardIncompatibleDropHint { .. }
71+
| StatementKind::Nop => false,
72+
73+
StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
74+
bug!("{:?} not found in this MIR phase!", stmt_kind)
75+
}
76+
}
77+
}
78+
}
79+
2780
/// Performs the optimization on the body
2881
///
2982
/// The `borrowed` set must be a `DenseBitSet` of all the locals that are ever borrowed in this
@@ -36,9 +89,7 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
3689
let mut always_live = debuginfo_locals(body);
3790
always_live.union(&borrowed_locals);
3891

39-
let mut live = MaybeTransitiveLiveLocals::new(&always_live)
40-
.iterate_to_fixpoint(tcx, body, None)
41-
.into_results_cursor(body);
92+
let mut analysis = DeadStoreAnalysis::new(tcx, body, &always_live);
4293

4394
// For blocks with a call terminator, if an argument copy can be turned into a move,
4495
// record it as (block, argument index).
@@ -50,8 +101,8 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
50101
let loc = Location { block: bb, statement_index: bb_data.statements.len() };
51102

52103
// Position ourselves between the evaluation of `args` and the write to `destination`.
53-
live.seek_to_block_end(bb);
54-
let mut state = live.get().clone();
104+
analysis.live.seek_to_block_end(bb);
105+
let mut state = analysis.live.get().clone();
55106

56107
for (index, arg) in args.iter().map(|a| &a.node).enumerate().rev() {
57108
if let Operand::Copy(place) = *arg
@@ -73,38 +124,10 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
73124
LivenessTransferFunction(&mut state).visit_operand(arg, loc);
74125
}
75126
}
76-
77127
for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
78128
let loc = Location { block: bb, statement_index };
79-
if let StatementKind::Assign(assign) = &statement.kind {
80-
if !assign.1.is_safe_to_remove() {
81-
continue;
82-
}
83-
}
84-
match &statement.kind {
85-
StatementKind::Assign(box (place, _))
86-
| StatementKind::SetDiscriminant { place: box place, .. }
87-
| StatementKind::Deinit(box place) => {
88-
if !place.is_indirect() && !always_live.contains(place.local) {
89-
live.seek_before_primary_effect(loc);
90-
if !live.get().contains(place.local) {
91-
patch.push(loc);
92-
}
93-
}
94-
}
95-
StatementKind::Retag(_, _)
96-
| StatementKind::StorageLive(_)
97-
| StatementKind::StorageDead(_)
98-
| StatementKind::Coverage(_)
99-
| StatementKind::Intrinsic(_)
100-
| StatementKind::ConstEvalCounter
101-
| StatementKind::PlaceMention(_)
102-
| StatementKind::BackwardIncompatibleDropHint { .. }
103-
| StatementKind::Nop => {}
104-
105-
StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
106-
bug!("{:?} not found in this MIR phase!", statement.kind)
107-
}
129+
if analysis.is_dead_store(loc, &statement.kind) {
130+
patch.push(loc);
108131
}
109132
}
110133
}

0 commit comments

Comments
 (0)