Skip to content

Commit 0af2e44

Browse files
committed
Auto merge of #155022 - tmandry:remove-dead-drops, r=<try>
Remove redundant drop terminators ahead of mir_coroutine_witnesses
2 parents 8317fef + 20a428d commit 0af2e44

40 files changed

Lines changed: 686 additions & 904 deletions

File tree

compiler/rustc_middle/src/queries.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,11 @@ rustc_queries! {
672672
desc { "promoting constants in MIR for `{}`", tcx.def_path_str(key) }
673673
}
674674

675+
query mir_post_borrowck_cleanup(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
676+
no_hash
677+
desc { "post borrowck cleanup of MIR for `{}`", tcx.def_path_str(key) }
678+
}
679+
675680
query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
676681
desc {
677682
"finding symbols for captures of closure `{}`",

compiler/rustc_mir_transform/src/coroutine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,7 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>(
13921392
tcx: TyCtxt<'tcx>,
13931393
def_id: LocalDefId,
13941394
) -> Option<CoroutineLayout<'tcx>> {
1395-
let (body, _) = tcx.mir_promoted(def_id);
1395+
let body = tcx.mir_post_borrowck_cleanup(def_id);
13961396
let body = body.borrow();
13971397
let body = &*body;
13981398

compiler/rustc_mir_transform/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ declare_passes! {
171171
mod promote_consts : PromoteTemps;
172172
mod ref_prop : ReferencePropagation;
173173
mod remove_noop_landing_pads : RemoveNoopLandingPads;
174+
mod remove_dead_drops : RemoveDeadDrops;
174175
mod remove_place_mention : RemovePlaceMention;
175176
mod remove_storage_markers : RemoveStorageMarkers;
176177
mod remove_uninit_drops : RemoveUninitDrops;
@@ -221,6 +222,7 @@ pub fn provide(providers: &mut Providers) {
221222
mir_built,
222223
mir_const_qualif,
223224
mir_promoted,
225+
mir_post_borrowck_cleanup,
224226
mir_drops_elaborated_and_const_checked,
225227
mir_for_ctfe,
226228
mir_coroutine_witnesses: coroutine::mir_coroutine_witnesses,
@@ -485,6 +487,19 @@ fn mir_promoted(
485487
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
486488
}
487489

490+
fn mir_post_borrowck_cleanup(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
491+
let (body, _) = tcx.mir_promoted(def);
492+
let mut body = body.borrow().clone();
493+
pm::run_passes(
494+
tcx,
495+
&mut body,
496+
&[&remove_dead_drops::RemoveDeadDrops],
497+
None,
498+
pm::Optimizations::Allowed,
499+
);
500+
tcx.alloc_steal_mir(body)
501+
}
502+
488503
/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
489504
fn mir_for_ctfe(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &Body<'_> {
490505
debug_assert!(!tcx.is_trivial_const(def_id), "Tried to get mir_for_ctfe of a trivial const");
@@ -543,7 +558,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
543558

544559
tcx.ensure_done().check_liveness(def);
545560

546-
let (body, _) = tcx.mir_promoted(def);
561+
let body = tcx.mir_post_borrowck_cleanup(def);
547562
let mut body = body.steal();
548563

549564
if let Some(error_reported) = tainted_by_errors {
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use rustc_index::bit_set::DenseBitSet;
2+
use rustc_middle::mir::*;
3+
use rustc_middle::ty::TyCtxt;
4+
use rustc_mir_dataflow::{Analysis, GenKill};
5+
6+
use super::simplify::simplify_cfg;
7+
8+
pub(crate) struct RemoveDeadDrops;
9+
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+
80+
impl<'tcx> crate::MirPass<'tcx> for RemoveDeadDrops {
81+
fn is_required(&self) -> bool {
82+
true
83+
}
84+
85+
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
86+
let mut maybe_init_cursor = MaybeInitializedLocals
87+
.iterate_to_fixpoint(tcx, body, None)
88+
.into_results_cursor(body);
89+
90+
let mut dead_drops = Vec::new();
91+
92+
for (block, data) in body.basic_blocks.iter_enumerated() {
93+
if let Some(terminator) = &data.terminator
94+
&& let TerminatorKind::Drop { place, target, .. } = &terminator.kind
95+
{
96+
let term_location = Location { block, statement_index: data.statements.len() };
97+
maybe_init_cursor.seek_before_primary_effect(term_location);
98+
99+
let is_dead = !maybe_init_cursor.get().contains(place.local);
100+
if is_dead {
101+
dead_drops.push((block, *target));
102+
}
103+
}
104+
}
105+
106+
if !dead_drops.is_empty() {
107+
for (block, target) in dead_drops {
108+
if let Some(terminator) = &mut body.basic_blocks.as_mut()[block].terminator {
109+
terminator.kind = TerminatorKind::Goto { target };
110+
}
111+
}
112+
113+
// Removing drop terminators may simplify the CFG, so run cleanup.
114+
simplify_cfg(tcx, body);
115+
}
116+
}
117+
}

tests/mir-opt/basic_assignment.main.ElaborateDrops.diff

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -35,53 +35,23 @@
3535
StorageLive(_5);
3636
StorageLive(_6);
3737
_6 = move _4;
38-
- drop(_5) -> [return: bb1, unwind: bb2];
39-
+ goto -> bb1;
40-
}
41-
42-
bb1: {
4338
_5 = move _6;
44-
- drop(_6) -> [return: bb3, unwind: bb6];
45-
+ goto -> bb3;
46-
}
47-
48-
bb2 (cleanup): {
49-
_5 = move _6;
50-
- drop(_6) -> [return: bb6, unwind terminate(cleanup)];
51-
+ goto -> bb6;
52-
}
53-
54-
bb3: {
5539
StorageDead(_6);
5640
_0 = const ();
57-
drop(_5) -> [return: bb4, unwind: bb7];
41+
- drop(_5) -> [return: bb1, unwind continue];
42+
+ drop(_5) -> [return: bb1, unwind: bb2];
5843
}
5944

60-
bb4: {
45+
bb1: {
6146
StorageDead(_5);
62-
- drop(_4) -> [return: bb5, unwind continue];
63-
+ goto -> bb5;
64-
}
65-
66-
bb5: {
6747
StorageDead(_4);
6848
StorageDead(_2);
6949
StorageDead(_1);
7050
return;
71-
}
72-
73-
bb6 (cleanup): {
74-
- drop(_5) -> [return: bb7, unwind terminate(cleanup)];
75-
+ goto -> bb7;
76-
}
77-
78-
bb7 (cleanup): {
79-
- drop(_4) -> [return: bb8, unwind terminate(cleanup)];
80-
+ goto -> bb8;
81-
}
82-
83-
bb8 (cleanup): {
84-
resume;
51+
+ }
52+
+
53+
+ bb2 (cleanup): {
54+
+ resume;
8555
}
8656
}
8757

0 commit comments

Comments
 (0)