Skip to content

Commit 70b5407

Browse files
committed
Use MaybeUninitializedLocals analysis in GVN mir-opt to remove fewer storage statements
1 parent 286b17a commit 70b5407

File tree

138 files changed

+729
-844
lines changed

Some content is hidden

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

138 files changed

+729
-844
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ use rustc_middle::mir::visit::*;
104104
use rustc_middle::mir::*;
105105
use rustc_middle::ty::layout::HasTypingEnv;
106106
use rustc_middle::ty::{self, Ty, TyCtxt};
107+
use rustc_mir_dataflow::impls::MaybeUninitializedLocals;
108+
use rustc_mir_dataflow::{Analysis, ResultsCursor};
107109
use rustc_span::DUMMY_SP;
108110
use smallvec::SmallVec;
109111
use tracing::{debug, instrument, trace};
@@ -139,10 +141,31 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
139141
state.visit_basic_block_data(bb, data);
140142
}
141143

142-
// For each local that is reused (`y` above), we remove its storage statements do avoid any
143-
// difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage
144-
// statements.
145-
StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
144+
// If we emit storage annotations, use `MaybeStorageDead` to check which reused locals
145+
// require storage removal (making them alive for the duration of the function).
146+
let storage_to_remove = if tcx.sess.emit_lifetime_markers() {
147+
let maybe_uninit = MaybeUninitializedLocals::new()
148+
.iterate_to_fixpoint(tcx, body, Some("mir_opt::gvn"))
149+
.into_results_cursor(body);
150+
151+
let mut storage_checker = StorageChecker {
152+
storage_to_check: state.reused_locals.clone(),
153+
storage_to_remove: DenseBitSet::new_empty(body.local_decls.len()),
154+
maybe_uninit,
155+
};
156+
157+
storage_checker.visit_body(body);
158+
159+
storage_checker.storage_to_remove
160+
} else {
161+
// Conservatively remove all storage statements for reused locals.
162+
state.reused_locals.clone()
163+
};
164+
165+
debug!(?storage_to_remove);
166+
167+
StorageRemover { tcx, reused_locals: state.reused_locals, storage_to_remove }
168+
.visit_body_preserves_cfg(body);
146169
}
147170

148171
fn is_required(&self) -> bool {
@@ -1781,6 +1804,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
17811804
struct StorageRemover<'tcx> {
17821805
tcx: TyCtxt<'tcx>,
17831806
reused_locals: DenseBitSet<Local>,
1807+
storage_to_remove: DenseBitSet<Local>,
17841808
}
17851809

17861810
impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> {
@@ -1801,11 +1825,48 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> {
18011825
match stmt.kind {
18021826
// When removing storage statements, we need to remove both (#107511).
18031827
StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
1804-
if self.reused_locals.contains(l) =>
1828+
if self.storage_to_remove.contains(l) =>
18051829
{
18061830
stmt.make_nop()
18071831
}
18081832
_ => self.super_statement(stmt, loc),
18091833
}
18101834
}
18111835
}
1836+
1837+
struct StorageChecker<'a, 'tcx> {
1838+
storage_to_check: DenseBitSet<Local>,
1839+
storage_to_remove: DenseBitSet<Local>,
1840+
maybe_uninit: ResultsCursor<'a, 'tcx, MaybeUninitializedLocals>,
1841+
}
1842+
1843+
impl<'a, 'tcx> Visitor<'tcx> for StorageChecker<'a, 'tcx> {
1844+
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
1845+
match context {
1846+
// These mutating uses do not require the local to be initialized.
1847+
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)
1848+
| PlaceContext::MutatingUse(MutatingUseContext::Call)
1849+
| PlaceContext::MutatingUse(MutatingUseContext::Store)
1850+
| PlaceContext::MutatingUse(MutatingUseContext::Yield)
1851+
| PlaceContext::NonUse(_) => {
1852+
return;
1853+
}
1854+
// Must check validity for other mutating usages and all non-mutating uses.
1855+
PlaceContext::MutatingUse(_) | PlaceContext::NonMutatingUse(_) => {}
1856+
}
1857+
1858+
if self.storage_to_check.contains(local) {
1859+
self.maybe_uninit.seek_before_primary_effect(location);
1860+
1861+
if self.maybe_uninit.get().contains(local) {
1862+
debug!(
1863+
?location,
1864+
?local,
1865+
"local is maybe uninit in this location, removing storage"
1866+
);
1867+
self.storage_to_remove.insert(local);
1868+
self.storage_to_check.remove(local);
1869+
}
1870+
}
1871+
}
1872+
}

tests/mir-opt/const_debuginfo.main.SingleUseConsts.diff

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@
5555
}
5656

5757
bb0: {
58-
nop;
58+
StorageLive(_1);
5959
- _1 = const 1_u8;
60-
nop;
61-
- _2 = const 2_u8;
62-
nop;
63-
- _3 = const 3_u8;
6460
+ nop;
61+
StorageLive(_2);
62+
- _2 = const 2_u8;
6563
+ nop;
64+
StorageLive(_3);
65+
- _3 = const 3_u8;
6666
+ nop;
6767
StorageLive(_4);
6868
StorageLive(_5);
@@ -95,7 +95,7 @@
9595
- _12 = const Point {{ x: 32_u32, y: 32_u32 }};
9696
+ nop;
9797
StorageLive(_13);
98-
nop;
98+
StorageLive(_14);
9999
- _14 = const 32_u32;
100100
+ nop;
101101
StorageLive(_15);
@@ -104,17 +104,17 @@
104104
+ nop;
105105
+ nop;
106106
StorageDead(_15);
107-
nop;
107+
StorageDead(_14);
108108
_0 = const ();
109109
StorageDead(_13);
110110
StorageDead(_12);
111111
StorageDead(_11);
112112
StorageDead(_10);
113113
StorageDead(_9);
114114
StorageDead(_4);
115-
nop;
116-
nop;
117-
nop;
115+
StorageDead(_3);
116+
StorageDead(_2);
117+
StorageDead(_1);
118118
return;
119119
}
120120
}

tests/mir-opt/const_prop/aggregate.main.GVN.panic-abort.diff

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
}
1414

1515
bb0: {
16-
- StorageLive(_1);
17-
+ nop;
16+
StorageLive(_1);
1817
StorageLive(_2);
1918
StorageLive(_3);
2019
_3 = (const 0_i32, const 1_u8, const 2_i32);
@@ -36,8 +35,7 @@
3635
StorageDead(_5);
3736
StorageDead(_4);
3837
_0 = const ();
39-
- StorageDead(_1);
40-
+ nop;
38+
StorageDead(_1);
4139
return;
4240
}
4341
}

tests/mir-opt/const_prop/aggregate.main.GVN.panic-unwind.diff

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
}
1414

1515
bb0: {
16-
- StorageLive(_1);
17-
+ nop;
16+
StorageLive(_1);
1817
StorageLive(_2);
1918
StorageLive(_3);
2019
_3 = (const 0_i32, const 1_u8, const 2_i32);
@@ -36,8 +35,7 @@
3635
StorageDead(_5);
3736
StorageDead(_4);
3837
_0 = const ();
39-
- StorageDead(_1);
40-
+ nop;
38+
StorageDead(_1);
4139
return;
4240
}
4341
}

tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-abort.diff

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
}
1919

2020
bb0: {
21-
- StorageLive(_1);
22-
+ nop;
21+
StorageLive(_1);
2322
_1 = const 0_i32;
2423
StorageLive(_2);
2524
StorageLive(_3);
@@ -48,8 +47,7 @@
4847
StorageDead(_3);
4948
_0 = const ();
5049
StorageDead(_2);
51-
- StorageDead(_1);
52-
+ nop;
50+
StorageDead(_1);
5351
return;
5452
}
5553
}

tests/mir-opt/const_prop/bad_op_div_by_zero.main.GVN.panic-unwind.diff

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
}
1919

2020
bb0: {
21-
- StorageLive(_1);
22-
+ nop;
21+
StorageLive(_1);
2322
_1 = const 0_i32;
2423
StorageLive(_2);
2524
StorageLive(_3);
@@ -48,8 +47,7 @@
4847
StorageDead(_3);
4948
_0 = const ();
5049
StorageDead(_2);
51-
- StorageDead(_1);
52-
+ nop;
50+
StorageDead(_1);
5351
return;
5452
}
5553
}

tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-abort.diff

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
}
1919

2020
bb0: {
21-
- StorageLive(_1);
22-
+ nop;
21+
StorageLive(_1);
2322
_1 = const 0_i32;
2423
StorageLive(_2);
2524
StorageLive(_3);
@@ -48,8 +47,7 @@
4847
StorageDead(_3);
4948
_0 = const ();
5049
StorageDead(_2);
51-
- StorageDead(_1);
52-
+ nop;
50+
StorageDead(_1);
5351
return;
5452
}
5553
}

tests/mir-opt/const_prop/bad_op_mod_by_zero.main.GVN.panic-unwind.diff

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
}
1919

2020
bb0: {
21-
- StorageLive(_1);
22-
+ nop;
21+
StorageLive(_1);
2322
_1 = const 0_i32;
2423
StorageLive(_2);
2524
StorageLive(_3);
@@ -48,8 +47,7 @@
4847
StorageDead(_3);
4948
_0 = const ();
5049
StorageDead(_2);
51-
- StorageDead(_1);
52-
+ nop;
50+
StorageDead(_1);
5351
return;
5452
}
5553
}

tests/mir-opt/const_prop/boolean_identities.test.GVN.diff

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@
1919
}
2020

2121
bb0: {
22-
- StorageLive(_3);
23-
+ nop;
22+
StorageLive(_3);
2423
StorageLive(_4);
2524
_4 = copy _2;
2625
- _3 = BitOr(move _4, const true);
2726
+ _3 = const true;
2827
StorageDead(_4);
29-
- StorageLive(_5);
30-
+ nop;
28+
StorageLive(_5);
3129
StorageLive(_6);
3230
_6 = copy _1;
3331
- _5 = BitAnd(move _6, const false);
@@ -43,10 +41,8 @@
4341
+ _0 = const false;
4442
StorageDead(_8);
4543
StorageDead(_7);
46-
- StorageDead(_5);
47-
- StorageDead(_3);
48-
+ nop;
49-
+ nop;
44+
StorageDead(_5);
45+
StorageDead(_3);
5046
return;
5147
}
5248
}

tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818

1919
bb0: {
2020
StorageLive(_1);
21-
- StorageLive(_2);
22-
+ nop;
21+
StorageLive(_2);
2322
StorageLive(_3);
2423
- _4 = SizeOf(i32);
2524
- _5 = AlignOf(i32);
@@ -39,9 +38,8 @@
3938
_9 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
4039
_2 = copy (*_9);
4140
- _1 = Add(move _2, const 0_i32);
42-
- StorageDead(_2);
4341
+ _1 = copy _2;
44-
+ nop;
42+
StorageDead(_2);
4543
drop(_3) -> [return: bb2, unwind unreachable];
4644
}
4745

0 commit comments

Comments
 (0)