Skip to content

Commit e4e6897

Browse files
committed
Just avoid creating too many opaques.
1 parent 42621a5 commit e4e6897

File tree

32 files changed

+687
-623
lines changed

32 files changed

+687
-623
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,13 @@ struct VnState<'body, 'a, 'tcx> {
227227
local_decls: &'body LocalDecls<'tcx>,
228228
is_coroutine: bool,
229229
/// Value stored in each local.
230-
locals: IndexVec<Local, VnIndex>,
230+
locals: IndexVec<Local, Option<VnIndex>>,
231231
/// Locals that are assigned that value.
232232
// This vector holds the locals that are SSA.
233-
rev_locals_ssa: IndexVec<VnIndex, SmallVec<[(Local, Location); 1]>>,
234-
// This vector holds the locals that are not SSA.
235-
rev_locals_non_ssa: FxHashMap<VnIndex, SmallVec<[(Local, Location); 1]>>,
233+
rev_locals_ssa: IndexVec<VnIndex, SmallVec<[(Local, BasicBlock); 1]>>,
234+
// This map holds the locals that are not SSA. This map is cleared at the end of each block.
235+
// Therefore, we do not need a location, the local always appears before the current location.
236+
rev_locals_non_ssa: FxHashMap<VnIndex, SmallVec<[Local; 1]>>,
236237
values: FxIndexSet<(Value<'a, 'tcx>, Ty<'tcx>)>,
237238
/// Values evaluated as constants if possible.
238239
evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>,
@@ -268,7 +269,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
268269
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
269270
local_decls,
270271
is_coroutine: body.coroutine.is_some(),
271-
locals: IndexVec::with_capacity(body.local_decls.len()),
272+
locals: IndexVec::from_elem(None, &body.local_decls),
272273
rev_locals_ssa: IndexVec::with_capacity(num_values),
273274
rev_locals_non_ssa: FxHashMap::default(),
274275
values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()),
@@ -280,14 +281,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
280281
reused_locals: DenseBitSet::new_empty(local_decls.len()),
281282
arena,
282283
};
283-
let init_loc = Location { block: START_BLOCK, statement_index: 0 };
284-
for decl in body.local_decls.iter() {
285-
let value = this.new_opaque(decl.ty);
286-
let local = this.locals.push(value);
284+
for local in body.args_iter() {
287285
if ssa.is_ssa(local) {
288-
this.rev_locals_ssa[value].push((local, init_loc));
289-
} else {
290-
this.rev_locals_non_ssa.entry(value).or_default().push((local, init_loc));
286+
let ty = body.local_decls[local].ty;
287+
let value = this.new_opaque(ty);
288+
this.rev_locals_ssa[value].push((local, START_BLOCK));
289+
this.locals[local] = Some(value);
291290
}
292291
}
293292
this
@@ -344,7 +343,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
344343

345344
let mut projection = place.projection.iter();
346345
let base = if place.is_indirect_first_projection() {
347-
let base = self.locals[place.local];
346+
let base = self.local(place.local);
348347
// Skip the initial `Deref`.
349348
projection.next();
350349
AddressBase::Deref(base)
@@ -356,7 +355,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
356355
.arena
357356
.try_alloc_from_iter(
358357
projection
359-
.map(|proj| proj.try_map(|value| Some(self.locals[value]), |ty| ty).ok_or(())),
358+
.map(|proj| proj.try_map(|value| Some(self.local(value)), |ty| ty).ok_or(())),
360359
)
361360
.ok()?;
362361
let value = Value::Address { base, projection, kind, provenance: self.next_opaque() };
@@ -376,12 +375,24 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
376375
/// Record that `local` is assigned `value`.
377376
#[instrument(level = "trace", skip(self))]
378377
fn assign(&mut self, local: Local, value: VnIndex, loc: Location) {
379-
self.locals[local] = value;
378+
self.locals[local] = Some(value);
380379
if self.ssa.is_ssa(local) {
381-
self.rev_locals_ssa[value].push((local, loc));
380+
self.rev_locals_ssa[value].push((local, loc.block));
382381
} else {
383-
self.rev_locals_non_ssa.entry(value).or_default().push((local, loc));
382+
self.rev_locals_non_ssa.entry(value).or_default().push(local);
383+
}
384+
}
385+
386+
/// Return the value assigned to a local, or assign an opaque value and return it.
387+
#[instrument(level = "trace", skip(self), ret)]
388+
fn local(&mut self, local: Local) -> VnIndex {
389+
if let Some(value) = self.locals[local] {
390+
return value;
384391
}
392+
let value = self.new_opaque(self.local_decls[local].ty);
393+
self.locals[local] = Some(value);
394+
self.rev_locals_non_ssa.entry(value).or_default().push(local);
395+
value
385396
}
386397

387398
#[instrument(level = "trace", skip(self))]
@@ -390,9 +401,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
390401
if this.ssa.is_ssa(local) {
391402
return;
392403
}
393-
let value = this.locals[local];
394-
this.rev_locals_non_ssa.entry(value).or_default().retain(|(l, _)| *l != local);
395-
this.locals[local] = this.new_opaque(this.ty(value));
404+
if let Some(value) = this.locals[local].take() {
405+
this.rev_locals_non_ssa.entry(value).or_default().retain(|l| *l != local);
406+
}
396407
};
397408
if place.is_indirect_first_projection() {
398409
// Non-local mutation maybe invalidate deref.
@@ -668,7 +679,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
668679
let (mut place_ty, mut value) = match base {
669680
// The base is a local, so we take the local's value and project from it.
670681
AddressBase::Local(local) => {
671-
let local = self.locals[local];
682+
let local = self.local(local);
672683
let place_ty = PlaceTy::from_ty(self.ty(local));
673684
(place_ty, local)
674685
}
@@ -774,7 +785,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
774785
// If the projection is indirect, we treat the local as a value, so can replace it with
775786
// another local.
776787
if place.is_indirect_first_projection()
777-
&& let base = self.locals[place.local]
788+
&& let base = self.local(place.local)
778789
&& let Some(new_local) = self.try_as_local(base, location)
779790
&& place.local != new_local
780791
{
@@ -787,7 +798,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
787798
for i in 0..projection.len() {
788799
let elem = projection[i];
789800
if let ProjectionElem::Index(idx_local) = elem {
790-
let idx = self.locals[idx_local];
801+
let idx = self.local(idx_local);
791802
if let Some(offset) = self.evaluated[idx].as_ref()
792803
&& let Some(offset) = self.ecx.read_target_usize(offset).discard_err()
793804
&& let Some(min_length) = offset.checked_add(1)
@@ -823,7 +834,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
823834
let mut place_ref = place.as_ref();
824835

825836
// Invariant: `value` holds the value up-to the `index`th projection excluded.
826-
let mut value = self.locals[place.local];
837+
let mut value = self.local(place.local);
827838
// Invariant: `value` has type `place_ty`, with optional downcast variant if needed.
828839
let mut place_ty = PlaceTy::from_ty(self.local_decls[place.local].ty);
829840
for (index, proj) in place.projection.iter().enumerate() {
@@ -834,7 +845,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
834845
place_ref = PlaceRef { local, projection: &place.projection[index..] };
835846
}
836847

837-
let Some(proj) = proj.try_map(|value| Some(self.locals[value]), |ty| ty) else {
848+
let Some(proj) = proj.try_map(|value| Some(self.local(value)), |ty| ty) else {
838849
return Err(place_ref);
839850
};
840851
let Some(ty_and_value) = self.project(place_ty, value, proj) else {
@@ -1770,15 +1781,15 @@ impl<'tcx> VnState<'_, '_, 'tcx> {
17701781
#[instrument(level = "trace", skip(self), ret)]
17711782
fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option<Local> {
17721783
let ssa = self.rev_locals_ssa.get(index)?;
1773-
let non_ssa = self.rev_locals_non_ssa.entry(index).or_default();
1774-
ssa.iter()
1775-
.chain(non_ssa.iter())
1776-
.find(|&&(other, assign_loc)| {
1777-
self.ssa.assignment_dominates(&self.dominators, other, loc)
1778-
|| (assign_loc.block == loc.block
1779-
&& assign_loc.statement_index < loc.statement_index)
1780-
})
1781-
.map(|&(other, _)| other)
1784+
if let Some((other, _)) = ssa.iter().find(|&&(other, assign_block)| {
1785+
self.ssa.assignment_dominates(&self.dominators, other, loc) || assign_block == loc.block
1786+
}) {
1787+
Some(*other)
1788+
} else if let Some(non_ssa) = self.rev_locals_non_ssa.get(&index) {
1789+
non_ssa.first().copied()
1790+
} else {
1791+
None
1792+
}
17821793
}
17831794
}
17841795

@@ -1791,13 +1802,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
17911802
self.rev_locals_non_ssa.clear();
17921803
for local in self.locals.indices() {
17931804
if !self.ssa.is_ssa(local) {
1794-
let current = self.locals[local];
1795-
let new = self.new_opaque(self.ty(current));
1796-
self.locals[local] = new;
1797-
self.rev_locals_non_ssa
1798-
.entry(new)
1799-
.or_default()
1800-
.push((local, Location { block, statement_index: 0 }));
1805+
self.locals[local] = None;
18011806
}
18021807
}
18031808
self.super_basic_block_data(block, bbdata);

tests/mir-opt/const_prop/discriminant.main.GVN.32bit.diff

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
bb0: {
1717
StorageLive(_1);
18-
StorageLive(_2);
18+
- StorageLive(_2);
19+
+ nop;
1920
StorageLive(_3);
2021
- _3 = Option::<bool>::Some(const true);
2122
- _4 = discriminant(_3);
@@ -41,8 +42,10 @@
4142
}
4243

4344
bb4: {
44-
_1 = Add(move _2, const 0_i32);
45-
StorageDead(_2);
45+
- _1 = Add(move _2, const 0_i32);
46+
- StorageDead(_2);
47+
+ _1 = copy _2;
48+
+ nop;
4649
StorageDead(_3);
4750
_0 = const ();
4851
StorageDead(_1);

tests/mir-opt/const_prop/discriminant.main.GVN.64bit.diff

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
bb0: {
1717
StorageLive(_1);
18-
StorageLive(_2);
18+
- StorageLive(_2);
19+
+ nop;
1920
StorageLive(_3);
2021
- _3 = Option::<bool>::Some(const true);
2122
- _4 = discriminant(_3);
@@ -41,8 +42,10 @@
4142
}
4243

4344
bb4: {
44-
_1 = Add(move _2, const 0_i32);
45-
StorageDead(_2);
45+
- _1 = Add(move _2, const 0_i32);
46+
- StorageDead(_2);
47+
+ _1 = copy _2;
48+
+ nop;
4649
StorageDead(_3);
4750
_0 = const ();
4851
StorageDead(_1);

tests/mir-opt/const_prop/discriminant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ fn main() {
2020
// CHECK: [[tmp]] = const 10_i32;
2121
// CHECK: goto -> bb4;
2222
// CHECK: bb4: {
23-
// CHECK: {{_.*}} = Add(move [[tmp]], const 0_i32);
23+
// CHECK: {{_.*}} = copy [[tmp]];
2424
let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0;
2525
}

tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@
7070
bb0: {
7171
StorageLive(_1);
7272
StorageLive(_2);
73-
- StorageLive(_3);
74-
+ nop;
73+
StorageLive(_3);
7574
StorageLive(_11);
7675
StorageLive(_12);
7776
StorageLive(_13);
@@ -89,8 +88,7 @@
8988
}
9089

9190
bb1: {
92-
- StorageDead(_3);
93-
+ nop;
91+
StorageDead(_3);
9492
StorageDead(_1);
9593
return;
9694
}
@@ -123,9 +121,8 @@
123121
StorageDead(_2);
124122
StorageLive(_4);
125123
- _9 = deref_copy _3;
126-
- _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
127124
+ _9 = copy _3;
128-
+ _10 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
125+
_10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
129126
_4 = copy _10;
130127
- StorageLive(_5);
131128
+ nop;
@@ -142,7 +139,7 @@
142139
StorageLive(_8);
143140
_8 = copy _5;
144141
- _7 = copy _8 as *mut () (PtrToPtr);
145-
+ _7 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
142+
+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
146143
StorageDead(_8);
147144
StorageDead(_7);
148145
- StorageDead(_5);

tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@
3636
bb0: {
3737
StorageLive(_1);
3838
StorageLive(_2);
39-
- StorageLive(_3);
40-
+ nop;
39+
StorageLive(_3);
4140
_3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue];
4241
}
4342

@@ -47,9 +46,8 @@
4746
StorageDead(_2);
4847
StorageLive(_4);
4948
- _9 = deref_copy _3;
50-
- _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
5149
+ _9 = copy _3;
52-
+ _10 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
50+
_10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
5351
_4 = copy _10;
5452
- StorageLive(_5);
5553
+ nop;
@@ -66,7 +64,7 @@
6664
StorageLive(_8);
6765
_8 = copy _5;
6866
- _7 = copy _8 as *mut () (PtrToPtr);
69-
+ _7 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
67+
+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
7068
StorageDead(_8);
7169
StorageDead(_7);
7270
- StorageDead(_5);
@@ -76,8 +74,7 @@
7674
}
7775

7876
bb2: {
79-
- StorageDead(_3);
80-
+ nop;
77+
StorageDead(_3);
8178
StorageDead(_1);
8279
return;
8380
}

tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@
7070
bb0: {
7171
StorageLive(_1);
7272
StorageLive(_2);
73-
- StorageLive(_3);
74-
+ nop;
73+
StorageLive(_3);
7574
StorageLive(_11);
7675
StorageLive(_12);
7776
StorageLive(_13);
@@ -89,8 +88,7 @@
8988
}
9089

9190
bb1: {
92-
- StorageDead(_3);
93-
+ nop;
91+
StorageDead(_3);
9492
StorageDead(_1);
9593
return;
9694
}
@@ -123,9 +121,8 @@
123121
StorageDead(_2);
124122
StorageLive(_4);
125123
- _9 = deref_copy _3;
126-
- _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
127124
+ _9 = copy _3;
128-
+ _10 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
125+
_10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
129126
_4 = copy _10;
130127
- StorageLive(_5);
131128
+ nop;
@@ -142,7 +139,7 @@
142139
StorageLive(_8);
143140
_8 = copy _5;
144141
- _7 = copy _8 as *mut () (PtrToPtr);
145-
+ _7 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
142+
+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
146143
StorageDead(_8);
147144
StorageDead(_7);
148145
- StorageDead(_5);

0 commit comments

Comments
 (0)