1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::impls::{borrowed_locals, MaybeTransitiveLiveLocals};
use rustc_mir_dataflow::Analysis;
pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitSet<Local>) {
let mut live = MaybeTransitiveLiveLocals::new(borrowed)
.into_engine(tcx, body)
.iterate_to_fixpoint()
.into_results_cursor(body);
let mut patch = Vec::new();
for (bb, bb_data) in traversal::preorder(body) {
for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
let loc = Location { block: bb, statement_index };
if let StatementKind::Assign(assign) = &statement.kind {
if !assign.1.is_safe_to_remove() {
continue;
}
}
match &statement.kind {
StatementKind::Assign(box (place, _))
| StatementKind::SetDiscriminant { place: box place, .. }
| StatementKind::Deinit(box place) => {
if !place.is_indirect() && !borrowed.contains(place.local) {
live.seek_before_primary_effect(loc);
if !live.get().contains(place.local) {
patch.push(loc);
}
}
}
StatementKind::Retag(_, _)
| StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)
| StatementKind::Coverage(_)
| StatementKind::Intrinsic(_)
| StatementKind::Nop => (),
StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
bug!("{:?} not found in this MIR phase!", &statement.kind)
}
}
}
}
if patch.is_empty() {
return;
}
let bbs = body.basic_blocks.as_mut_preserves_cfg();
for Location { block, statement_index } in patch {
bbs[block].statements[statement_index].make_nop();
}
crate::simplify::SimplifyLocals.run_pass(tcx, body)
}
pub struct DeadStoreElimination;
impl<'tcx> MirPass<'tcx> for DeadStoreElimination {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
sess.mir_opt_level() >= 2
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let borrowed = borrowed_locals(body);
eliminate(tcx, body, &borrowed);
}
}