Skip to content

Commit 20a428d

Browse files
committed
Use a coarse-grained analysis over locals
1 parent f42e47a commit 20a428d

3 files changed

Lines changed: 110 additions & 67 deletions

File tree

compiler/rustc_mir_transform/src/remove_dead_drops.rs

Lines changed: 74 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,89 @@
1+
use rustc_index::bit_set::DenseBitSet;
12
use rustc_middle::mir::*;
23
use rustc_middle::ty::TyCtxt;
3-
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
4-
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData};
5-
use rustc_mir_dataflow::{Analysis, MaybeReachable};
4+
use rustc_mir_dataflow::{Analysis, GenKill};
65

76
use super::simplify::simplify_cfg;
87

98
pub(crate) struct RemoveDeadDrops;
109

10+
use rustc_middle::mir::visit::*;
11+
12+
struct MaybeInitializedLocals;
13+
14+
/// This is conservative: If any part of a local is initialized, we mark it
15+
/// initialized, while we only mark uninitialized if the whole local is moved
16+
/// from or StorageDead.
17+
struct TransferFunction<'a, T> {
18+
trans: &'a mut T,
19+
}
20+
21+
impl<'tcx, T: GenKill<Local>> Visitor<'tcx> for TransferFunction<'_, T> {
22+
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
23+
self.super_place(place, context, location);
24+
25+
if context.is_place_assignment() {
26+
self.trans.gen_(place.local);
27+
} else if matches!(
28+
context,
29+
PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
30+
) {
31+
self.trans.kill(place.local);
32+
}
33+
}
34+
35+
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
36+
self.super_operand(operand, location);
37+
38+
if let Operand::Move(place) = operand {
39+
if place.projection.is_empty() {
40+
self.trans.kill(place.local);
41+
}
42+
}
43+
}
44+
}
45+
46+
impl<'tcx> Analysis<'tcx> for MaybeInitializedLocals {
47+
type Domain = DenseBitSet<Local>;
48+
const NAME: &'static str = "maybe_initialized_locals";
49+
50+
fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
51+
DenseBitSet::new_empty(body.local_decls.len())
52+
}
53+
54+
fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
55+
for arg in 1..=body.arg_count {
56+
state.insert(Local::from_usize(arg));
57+
}
58+
}
59+
60+
fn apply_primary_statement_effect(
61+
&self,
62+
state: &mut Self::Domain,
63+
stmt: &Statement<'tcx>,
64+
location: Location,
65+
) {
66+
TransferFunction { trans: state }.visit_statement(stmt, location);
67+
}
68+
69+
fn apply_primary_terminator_effect<'mir>(
70+
&self,
71+
state: &mut Self::Domain,
72+
terminator: &'mir Terminator<'tcx>,
73+
location: Location,
74+
) -> TerminatorEdges<'mir, 'tcx> {
75+
TransferFunction { trans: state }.visit_terminator(terminator, location);
76+
terminator.edges()
77+
}
78+
}
79+
1180
impl<'tcx> crate::MirPass<'tcx> for RemoveDeadDrops {
1281
fn is_required(&self) -> bool {
1382
true
1483
}
1584

1685
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
17-
let move_data = MoveData::gather_moves(body, tcx, |_| true);
18-
19-
let mut maybe_init_cursor = MaybeInitializedPlaces::new(tcx, body, &move_data)
86+
let mut maybe_init_cursor = MaybeInitializedLocals
2087
.iterate_to_fixpoint(tcx, body, None)
2188
.into_results_cursor(body);
2289

@@ -26,18 +93,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveDeadDrops {
2693
if let Some(terminator) = &data.terminator
2794
&& let TerminatorKind::Drop { place, target, .. } = &terminator.kind
2895
{
29-
let LookupResult::Exact(path) = move_data.rev_lookup.find(place.as_ref()) else {
30-
continue;
31-
};
32-
3396
let term_location = Location { block, statement_index: data.statements.len() };
3497
maybe_init_cursor.seek_before_primary_effect(term_location);
3598

36-
let is_dead = match maybe_init_cursor.get() {
37-
MaybeReachable::Unreachable => true,
38-
MaybeReachable::Reachable(maybe_init) => !maybe_init.contains(path),
39-
};
40-
99+
let is_dead = !maybe_init_cursor.get().contains(place.local);
41100
if is_dead {
42101
dead_drops.push((block, *target));
43102
}

tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
4545
bb0: {
4646
_18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
4747
_17 = discriminant((*_18));
48-
switchInt(move _17) -> [0: bb1, 1: bb15, 3: bb13, 4: bb14, otherwise: bb16];
48+
switchInt(move _17) -> [0: bb1, 1: bb13, 3: bb11, 4: bb12, otherwise: bb14];
4949
}
5050

5151
bb1: {
@@ -77,10 +77,6 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
7777

7878
bb4: {
7979
StorageDead(_4);
80-
drop(_3) -> [return: bb5, unwind unreachable];
81-
}
82-
83-
bb5: {
8480
StorageDead(_3);
8581
StorageLive(_8);
8682
StorageLive(_9);
@@ -91,17 +87,17 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
9187
StorageLive(_12);
9288
StorageLive(_13);
9389
_13 = &(((*_18) as variant#4).0: std::string::String);
94-
_12 = <String as Clone>::clone(move _13) -> [return: bb6, unwind unreachable];
90+
_12 = <String as Clone>::clone(move _13) -> [return: bb5, unwind unreachable];
9591
}
9692

97-
bb6: {
93+
bb5: {
9894
StorageDead(_13);
9995
StorageLive(_14);
10096
StorageLive(_15);
101-
_15 = Location::<'_>::caller() -> [return: bb7, unwind unreachable];
97+
_15 = Location::<'_>::caller() -> [return: bb6, unwind unreachable];
10298
}
10399

104-
bb7: {
100+
bb6: {
105101
_14 = &(*_15);
106102
_9 = (move _10, move _12, move _14);
107103
StorageDead(_14);
@@ -116,54 +112,50 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
116112
return;
117113
}
118114

119-
bb8: {
115+
bb7: {
120116
StorageDead(_9);
121-
drop(_8) -> [return: bb9, unwind unreachable];
122-
}
123-
124-
bb9: {
125117
StorageDead(_15);
126118
StorageDead(_11);
127119
StorageDead(_8);
128120
_16 = const ();
129-
drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb10, unwind unreachable];
121+
drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb8, unwind unreachable];
130122
}
131123

132-
bb10: {
133-
goto -> bb12;
124+
bb8: {
125+
goto -> bb10;
134126
}
135127

136-
bb11: {
128+
bb9: {
137129
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
138130
discriminant((*_18)) = 1;
139131
return;
140132
}
141133

142-
bb12: {
143-
goto -> bb11;
134+
bb10: {
135+
goto -> bb9;
144136
}
145137

146-
bb13: {
138+
bb11: {
147139
StorageLive(_3);
148140
StorageLive(_4);
149141
_3 = move _2;
150142
goto -> bb4;
151143
}
152144

153-
bb14: {
145+
bb12: {
154146
StorageLive(_8);
155147
StorageLive(_9);
156148
StorageLive(_11);
157149
StorageLive(_15);
158150
_8 = move _2;
159-
goto -> bb8;
151+
goto -> bb7;
160152
}
161153

162-
bb15: {
163-
assert(const false, "coroutine resumed after completion") -> [success: bb15, unwind unreachable];
154+
bb13: {
155+
assert(const false, "coroutine resumed after completion") -> [success: bb13, unwind unreachable];
164156
}
165157

166-
bb16: {
158+
bb14: {
167159
unreachable;
168160
}
169161
}

tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
4545
bb0: {
4646
_18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
4747
_17 = discriminant((*_18));
48-
switchInt(move _17) -> [0: bb1, 1: bb15, 3: bb13, 4: bb14, otherwise: bb16];
48+
switchInt(move _17) -> [0: bb1, 1: bb13, 3: bb11, 4: bb12, otherwise: bb14];
4949
}
5050

5151
bb1: {
@@ -77,10 +77,6 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
7777

7878
bb4: {
7979
StorageDead(_4);
80-
drop(_3) -> [return: bb5, unwind unreachable];
81-
}
82-
83-
bb5: {
8480
StorageDead(_3);
8581
StorageLive(_8);
8682
StorageLive(_9);
@@ -91,17 +87,17 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
9187
StorageLive(_12);
9288
StorageLive(_13);
9389
_13 = &(((*_18) as variant#4).0: std::string::String);
94-
_12 = <String as Clone>::clone(move _13) -> [return: bb6, unwind unreachable];
90+
_12 = <String as Clone>::clone(move _13) -> [return: bb5, unwind unreachable];
9591
}
9692

97-
bb6: {
93+
bb5: {
9894
StorageDead(_13);
9995
StorageLive(_14);
10096
StorageLive(_15);
101-
_15 = Location::<'_>::caller() -> [return: bb7, unwind unreachable];
97+
_15 = Location::<'_>::caller() -> [return: bb6, unwind unreachable];
10298
}
10399

104-
bb7: {
100+
bb6: {
105101
_14 = &(*_15);
106102
_9 = (move _10, move _12, move _14);
107103
StorageDead(_14);
@@ -116,54 +112,50 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
116112
return;
117113
}
118114

119-
bb8: {
115+
bb7: {
120116
StorageDead(_9);
121-
drop(_8) -> [return: bb9, unwind unreachable];
122-
}
123-
124-
bb9: {
125117
StorageDead(_15);
126118
StorageDead(_11);
127119
StorageDead(_8);
128120
_16 = const ();
129-
drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb10, unwind unreachable];
121+
drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb8, unwind unreachable];
130122
}
131123

132-
bb10: {
133-
goto -> bb12;
124+
bb8: {
125+
goto -> bb10;
134126
}
135127

136-
bb11: {
128+
bb9: {
137129
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
138130
discriminant((*_18)) = 1;
139131
return;
140132
}
141133

142-
bb12: {
143-
goto -> bb11;
134+
bb10: {
135+
goto -> bb9;
144136
}
145137

146-
bb13: {
138+
bb11: {
147139
StorageLive(_3);
148140
StorageLive(_4);
149141
_3 = move _2;
150142
goto -> bb4;
151143
}
152144

153-
bb14: {
145+
bb12: {
154146
StorageLive(_8);
155147
StorageLive(_9);
156148
StorageLive(_11);
157149
StorageLive(_15);
158150
_8 = move _2;
159-
goto -> bb8;
151+
goto -> bb7;
160152
}
161153

162-
bb15: {
163-
assert(const false, "coroutine resumed after completion") -> [success: bb15, unwind unreachable];
154+
bb13: {
155+
assert(const false, "coroutine resumed after completion") -> [success: bb13, unwind unreachable];
164156
}
165157

166-
bb16: {
158+
bb14: {
167159
unreachable;
168160
}
169161
}

0 commit comments

Comments
 (0)