Skip to content

Commit 26fc160

Browse files
committed
Use MaybeUninitializedLocals analysis in GVN mir-opt to remove fewer storage statements
1 parent bddb8e4 commit 26fc160

File tree

139 files changed

+736
-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.

139 files changed

+736
-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, LayoutOf};
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 rustc_span::def_id::DefId;
109111
use smallvec::SmallVec;
@@ -140,10 +142,31 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
140142
state.visit_basic_block_data(bb, data);
141143
}
142144

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

149172
fn is_required(&self) -> bool {
@@ -1824,6 +1847,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
18241847
struct StorageRemover<'tcx> {
18251848
tcx: TyCtxt<'tcx>,
18261849
reused_locals: DenseBitSet<Local>,
1850+
storage_to_remove: DenseBitSet<Local>,
18271851
}
18281852

18291853
impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> {
@@ -1844,11 +1868,48 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> {
18441868
match stmt.kind {
18451869
// When removing storage statements, we need to remove both (#107511).
18461870
StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
1847-
if self.reused_locals.contains(l) =>
1871+
if self.storage_to_remove.contains(l) =>
18481872
{
18491873
stmt.make_nop()
18501874
}
18511875
_ => self.super_statement(stmt, loc),
18521876
}
18531877
}
18541878
}
1879+
1880+
struct StorageChecker<'a, 'tcx> {
1881+
storage_to_check: DenseBitSet<Local>,
1882+
storage_to_remove: DenseBitSet<Local>,
1883+
maybe_uninit: ResultsCursor<'a, 'tcx, MaybeUninitializedLocals>,
1884+
}
1885+
1886+
impl<'a, 'tcx> Visitor<'tcx> for StorageChecker<'a, 'tcx> {
1887+
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
1888+
match context {
1889+
// These mutating uses do not require the local to be initialized.
1890+
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)
1891+
| PlaceContext::MutatingUse(MutatingUseContext::Call)
1892+
| PlaceContext::MutatingUse(MutatingUseContext::Store)
1893+
| PlaceContext::MutatingUse(MutatingUseContext::Yield)
1894+
| PlaceContext::NonUse(_) => {
1895+
return;
1896+
}
1897+
// Must check validity for other mutating usages and all non-mutating uses.
1898+
PlaceContext::MutatingUse(_) | PlaceContext::NonMutatingUse(_) => {}
1899+
}
1900+
1901+
if self.storage_to_check.contains(local) {
1902+
self.maybe_uninit.seek_before_primary_effect(location);
1903+
1904+
if self.maybe_uninit.get().contains(local) {
1905+
debug!(
1906+
?location,
1907+
?local,
1908+
"local is maybe uninit in this location, removing storage"
1909+
);
1910+
self.storage_to_remove.insert(local);
1911+
self.storage_to_check.remove(local);
1912+
}
1913+
}
1914+
}
1915+
}

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

tests/mir-opt/const_prop/boxes.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
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: bb3];
4644
}
4745

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
}
2323

2424
bb0: {
25-
- StorageLive(_1);
26-
+ nop;
25+
StorageLive(_1);
2726
_1 = foo() -> [return: bb1, unwind unreachable];
2827
}
2928

@@ -44,8 +43,7 @@
4443
StorageDead(_5);
4544
StorageDead(_4);
4645
StorageDead(_2);
47-
- StorageDead(_1);
48-
+ nop;
46+
StorageDead(_1);
4947
return;
5048
}
5149
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
}
2323

2424
bb0: {
25-
- StorageLive(_1);
26-
+ nop;
25+
StorageLive(_1);
2726
_1 = foo() -> [return: bb1, unwind continue];
2827
}
2928

@@ -44,8 +43,7 @@
4443
StorageDead(_5);
4544
StorageDead(_4);
4645
StorageDead(_2);
47-
- StorageDead(_1);
48-
+ nop;
46+
StorageDead(_1);
4947
return;
5048
}
5149
}

0 commit comments

Comments
 (0)