Skip to content

Commit a457290

Browse files
committed
Make Value Copy by arena-allocating vectors.
1 parent 621cf12 commit a457290

File tree

1 file changed

+59
-56
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+59
-56
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ use std::borrow::Cow;
8888

8989
use either::Either;
9090
use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx};
91+
use rustc_arena::DroplessArena;
9192
use rustc_const_eval::const_eval::DummyMachine;
9293
use rustc_const_eval::interpret::{
9394
ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar,
@@ -126,7 +127,9 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
126127
// Clone dominators because we need them while mutating the body.
127128
let dominators = body.basic_blocks.dominators().clone();
128129

129-
let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls);
130+
let arena = DroplessArena::default();
131+
let mut state =
132+
VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls, &arena);
130133

131134
for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) {
132135
let opaque = state.new_opaque(body.local_decls[local].ty);
@@ -160,8 +163,8 @@ enum AddressKind {
160163
Address(RawPtrKind),
161164
}
162165

163-
#[derive(Debug, PartialEq, Eq, Hash)]
164-
enum Value<'tcx> {
166+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
167+
enum Value<'a, 'tcx> {
165168
// Root values.
166169
/// Used to represent values we know nothing about.
167170
/// The `usize` is a counter incremented by `new_opaque`.
@@ -176,7 +179,7 @@ enum Value<'tcx> {
176179
},
177180
/// An aggregate value, either tuple/closure/struct/enum.
178181
/// This does not contain unions, as we cannot reason with the value.
179-
Aggregate(VariantIdx, Vec<VnIndex>),
182+
Aggregate(VariantIdx, &'a [VnIndex]),
180183
/// A raw pointer aggregate built from a thin pointer and metadata.
181184
RawPtr {
182185
/// Thin pointer component. This is field 0 in MIR.
@@ -212,7 +215,7 @@ enum Value<'tcx> {
212215
},
213216
}
214217

215-
struct VnState<'body, 'tcx> {
218+
struct VnState<'body, 'a, 'tcx> {
216219
tcx: TyCtxt<'tcx>,
217220
ecx: InterpCx<'tcx, DummyMachine>,
218221
local_decls: &'body LocalDecls<'tcx>,
@@ -222,7 +225,7 @@ struct VnState<'body, 'tcx> {
222225
/// Locals that are assigned that value.
223226
// This vector does not hold all the values of `VnIndex` that we create.
224227
rev_locals: IndexVec<VnIndex, SmallVec<[Local; 1]>>,
225-
values: FxIndexSet<(Value<'tcx>, Ty<'tcx>)>,
228+
values: FxIndexSet<(Value<'a, 'tcx>, Ty<'tcx>)>,
226229
/// Values evaluated as constants if possible.
227230
evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>,
228231
/// Counter to generate different values.
@@ -232,16 +235,18 @@ struct VnState<'body, 'tcx> {
232235
ssa: &'body SsaLocals,
233236
dominators: Dominators<BasicBlock>,
234237
reused_locals: DenseBitSet<Local>,
238+
arena: &'a DroplessArena,
235239
}
236240

237-
impl<'body, 'tcx> VnState<'body, 'tcx> {
241+
impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
238242
fn new(
239243
tcx: TyCtxt<'tcx>,
240244
body: &Body<'tcx>,
241245
typing_env: ty::TypingEnv<'tcx>,
242246
ssa: &'body SsaLocals,
243247
dominators: Dominators<BasicBlock>,
244248
local_decls: &'body LocalDecls<'tcx>,
249+
arena: &'a DroplessArena,
245250
) -> Self {
246251
// Compute a rough estimate of the number of values in the body from the number of
247252
// statements. This is meant to reduce the number of allocations, but it's all right if
@@ -264,6 +269,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
264269
ssa,
265270
dominators,
266271
reused_locals: DenseBitSet::new_empty(local_decls.len()),
272+
arena,
267273
}
268274
}
269275

@@ -272,7 +278,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
272278
}
273279

274280
#[instrument(level = "trace", skip(self), ret)]
275-
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'tcx>) -> VnIndex {
281+
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'a, 'tcx>) -> VnIndex {
276282
let (index, new) = self.values.insert_full((value, ty));
277283
let index = VnIndex::from_usize(index);
278284
if new {
@@ -315,8 +321,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
315321
}
316322

317323
#[inline]
318-
fn get(&self, index: VnIndex) -> &Value<'tcx> {
319-
&self.values.get_index(index.as_usize()).unwrap().0
324+
fn get(&self, index: VnIndex) -> Value<'a, 'tcx> {
325+
self.values.get_index(index.as_usize()).unwrap().0
320326
}
321327

322328
#[inline]
@@ -361,8 +367,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
361367
self.insert(ty, Value::Constant { value, disambiguator: 0 })
362368
}
363369

364-
fn insert_tuple(&mut self, ty: Ty<'tcx>, values: Vec<VnIndex>) -> VnIndex {
365-
self.insert(ty, Value::Aggregate(VariantIdx::ZERO, values))
370+
fn insert_tuple(&mut self, ty: Ty<'tcx>, values: &[VnIndex]) -> VnIndex {
371+
self.insert(ty, Value::Aggregate(VariantIdx::ZERO, self.arena.alloc_slice(values)))
366372
}
367373

368374
fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex {
@@ -388,7 +394,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
388394
} else {
389395
return None;
390396
};
391-
let op = match *self.get(value) {
397+
let op = match self.get(value) {
392398
_ if ty.is_zst() => ImmTy::uninit(ty).into(),
393399

394400
Opaque(_) => return None,
@@ -608,7 +614,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
608614
if let Value::Aggregate(_, fields) = self.get(value) {
609615
return Some((projection_ty, fields[f.as_usize()]));
610616
} else if let Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)) = self.get(value)
611-
&& let Value::Aggregate(written_variant, fields) = self.get(*outer_value)
617+
&& let Value::Aggregate(written_variant, fields) = self.get(outer_value)
612618
// This pass is not aware of control-flow, so we do not know whether the
613619
// replacement we are doing is actually reachable. We could be in any arm of
614620
// ```
@@ -633,15 +639,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
633639
ProjectionElem::Index(idx) => {
634640
if let Value::Repeat(inner, _) = self.get(value) {
635641
*from_non_ssa_index |= self.locals[idx].is_none();
636-
return Some((projection_ty, *inner));
642+
return Some((projection_ty, inner));
637643
}
638644
let idx = self.locals[idx]?;
639645
ProjectionElem::Index(idx)
640646
}
641647
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
642648
match self.get(value) {
643649
Value::Repeat(inner, _) => {
644-
return Some((projection_ty, *inner));
650+
return Some((projection_ty, inner));
645651
}
646652
Value::Aggregate(_, operands) => {
647653
let offset = if from_end {
@@ -731,8 +737,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
731737
let mut place_ty = PlaceTy::from_ty(self.local_decls[place.local].ty);
732738
let mut from_non_ssa_index = false;
733739
for (index, proj) in place.projection.iter().enumerate() {
734-
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
735-
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
740+
if let Value::Projection(pointer, ProjectionElem::Deref) = self.get(value)
741+
&& let Value::Address { place: mut pointee, kind, .. } = self.get(pointer)
736742
&& let AddressKind::Ref(BorrowKind::Shared) = kind
737743
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
738744
{
@@ -755,8 +761,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
755761
(place_ty, value) = self.project(place_ty, value, proj, &mut from_non_ssa_index)?;
756762
}
757763

758-
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
759-
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
764+
if let Value::Projection(pointer, ProjectionElem::Deref) = self.get(value)
765+
&& let Value::Address { place: mut pointee, kind, .. } = self.get(pointer)
760766
&& let AddressKind::Ref(BorrowKind::Shared) = kind
761767
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
762768
{
@@ -868,7 +874,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
868874
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
869875
let enum_ty = self.ty(place);
870876
if enum_ty.is_enum()
871-
&& let Value::Aggregate(variant, _) = *self.get(place)
877+
&& let Value::Aggregate(variant, _) = self.get(place)
872878
{
873879
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).discard_err()?;
874880
return Some(self.insert_scalar(discr.layout.ty, discr.to_scalar()));
@@ -904,12 +910,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
904910
let Some(&first_field) = fields.first() else {
905911
return None;
906912
};
907-
let Value::Projection(copy_from_value, _) = *self.get(first_field) else {
913+
let Value::Projection(copy_from_value, _) = self.get(first_field) else {
908914
return None;
909915
};
910916
// All fields must correspond one-to-one and come from the same aggregate value.
911917
if fields.iter().enumerate().any(|(index, &v)| {
912-
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = *self.get(v)
918+
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = self.get(v)
913919
&& copy_from_value == pointer
914920
&& from_index.index() == index
915921
{
@@ -921,7 +927,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
921927
}
922928

923929
let mut copy_from_local_value = copy_from_value;
924-
if let Value::Projection(pointer, proj) = *self.get(copy_from_value)
930+
if let Value::Projection(pointer, proj) = self.get(copy_from_value)
925931
&& let ProjectionElem::Downcast(_, read_variant) = proj
926932
{
927933
if variant_index == read_variant {
@@ -979,13 +985,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
979985
}
980986
}
981987

982-
let fields: Vec<_> = field_ops
983-
.iter_mut()
984-
.map(|op| {
985-
self.simplify_operand(op, location)
986-
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
987-
})
988-
.collect();
988+
let fields = self.arena.alloc_from_iter(field_ops.iter_mut().map(|op| {
989+
self.simplify_operand(op, location)
990+
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
991+
}));
989992

990993
let variant_index = match *kind {
991994
AggregateKind::Array(..) | AggregateKind::Tuple => {
@@ -1006,12 +1009,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10061009
let mut was_updated = false;
10071010
while let Value::Cast { kind: CastKind::PtrToPtr, value: cast_value } =
10081011
self.get(pointer)
1009-
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(*cast_value).kind()
1012+
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(cast_value).kind()
10101013
&& let ty::RawPtr(_, output_mtbl) = ty.kind()
10111014
&& from_mtbl == output_mtbl
10121015
&& from_pointee_ty.is_sized(self.tcx, self.typing_env())
10131016
{
1014-
pointer = *cast_value;
1017+
pointer = cast_value;
10151018
was_updated = true;
10161019
}
10171020

@@ -1069,9 +1072,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10691072
// To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
10701073
// it's fine to get a projection as the type.
10711074
Value::Cast { kind: CastKind::PtrToPtr, value: inner }
1072-
if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) =>
1075+
if self.pointers_have_same_metadata(self.ty(inner), arg_ty) =>
10731076
{
1074-
arg_index = *inner;
1077+
arg_index = inner;
10751078
was_updated = true;
10761079
continue;
10771080
}
@@ -1098,15 +1101,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10981101
}
10991102

11001103
let value = match (op, self.get(arg_index)) {
1101-
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner),
1102-
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner),
1104+
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(inner),
1105+
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(inner),
11031106
(UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => {
1104-
Value::BinaryOp(BinOp::Ne, *lhs, *rhs)
1107+
Value::BinaryOp(BinOp::Ne, lhs, rhs)
11051108
}
11061109
(UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
1107-
Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
1110+
Value::BinaryOp(BinOp::Eq, lhs, rhs)
11081111
}
1109-
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(*metadata),
1112+
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(metadata),
11101113
// We have an unsizing cast, which assigns the length to wide pointer metadata.
11111114
(
11121115
UnOp::PtrMetadata,
@@ -1115,7 +1118,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11151118
value: inner,
11161119
},
11171120
) if let ty::Slice(..) = arg_ty.builtin_deref(true).unwrap().kind()
1118-
&& let ty::Array(_, len) = self.ty(*inner).builtin_deref(true).unwrap().kind() =>
1121+
&& let ty::Array(_, len) = self.ty(inner).builtin_deref(true).unwrap().kind() =>
11191122
{
11201123
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
11211124
}
@@ -1148,12 +1151,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11481151
&& lhs_ty.is_any_ptr()
11491152
&& let Value::Cast { kind: CastKind::PtrToPtr, value: lhs_value } = self.get(lhs)
11501153
&& let Value::Cast { kind: CastKind::PtrToPtr, value: rhs_value } = self.get(rhs)
1151-
&& let lhs_from = self.ty(*lhs_value)
1152-
&& lhs_from == self.ty(*rhs_value)
1154+
&& let lhs_from = self.ty(lhs_value)
1155+
&& lhs_from == self.ty(rhs_value)
11531156
&& self.pointers_have_same_metadata(lhs_from, lhs_ty)
11541157
{
1155-
lhs = *lhs_value;
1156-
rhs = *rhs_value;
1158+
lhs = lhs_value;
1159+
rhs = rhs_value;
11571160
if let Some(lhs_op) = self.try_as_operand(lhs, location)
11581161
&& let Some(rhs_op) = self.try_as_operand(rhs, location)
11591162
{
@@ -1287,7 +1290,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12871290
if op.is_overflowing() {
12881291
let ty = Ty::new_tup(self.tcx, &[self.ty(result), self.tcx.types.bool]);
12891292
let false_val = self.insert_bool(false);
1290-
Some(self.insert_tuple(ty, vec![result, false_val]))
1293+
Some(self.insert_tuple(ty, &[result, false_val]))
12911294
} else {
12921295
Some(result)
12931296
}
@@ -1340,11 +1343,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13401343
&& let ty::RawPtr(to_pointee, _) = to.kind()
13411344
&& to_pointee.is_sized(self.tcx, self.typing_env())
13421345
{
1343-
from = self.ty(*pointer);
1344-
value = *pointer;
1346+
from = self.ty(pointer);
1347+
value = pointer;
13451348
was_updated_this_iteration = true;
13461349
if from == to {
1347-
return Some(*pointer);
1350+
return Some(pointer);
13481351
}
13491352
}
13501353

@@ -1353,7 +1356,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13531356
if let Transmute = kind
13541357
&& let Value::Aggregate(variant_idx, field_values) = self.get(value)
13551358
&& let Some((field_idx, field_ty)) =
1356-
self.value_is_all_in_one_field(from, *variant_idx)
1359+
self.value_is_all_in_one_field(from, variant_idx)
13571360
{
13581361
from = field_ty;
13591362
value = field_values[field_idx.as_usize()];
@@ -1364,7 +1367,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13641367
}
13651368

13661369
// Various cast-then-cast cases can be simplified.
1367-
if let Value::Cast { kind: inner_kind, value: inner_value } = *self.get(value) {
1370+
if let Value::Cast { kind: inner_kind, value: inner_value } = self.get(value) {
13681371
let inner_from = self.ty(inner_value);
13691372
let new_kind = match (inner_kind, kind) {
13701373
// Even if there's a narrowing cast in here that's fine, because
@@ -1438,7 +1441,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
14381441
// We have an unsizing cast, which assigns the length to wide pointer metadata.
14391442
if let Value::Cast { kind, value: from } = self.get(inner)
14401443
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
1441-
&& let Some(from) = self.ty(*from).builtin_deref(true)
1444+
&& let Some(from) = self.ty(from).builtin_deref(true)
14421445
&& let ty::Array(_, len) = from.kind()
14431446
&& let Some(to) = self.ty(inner).builtin_deref(true)
14441447
&& let ty::Slice(..) = to.kind()
@@ -1596,7 +1599,7 @@ fn op_to_prop_const<'tcx>(
15961599
None
15971600
}
15981601

1599-
impl<'tcx> VnState<'_, 'tcx> {
1602+
impl<'tcx> VnState<'_, '_, 'tcx> {
16001603
/// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
16011604
/// returns that result as an [`Operand`].
16021605
fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option<Operand<'tcx>> {
@@ -1615,7 +1618,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16151618
// This was already constant in MIR, do not change it. If the constant is not
16161619
// deterministic, adding an additional mention of it in MIR will not give the same value as
16171620
// the former mention.
1618-
if let Value::Constant { value, disambiguator: 0 } = *self.get(index) {
1621+
if let Value::Constant { value, disambiguator: 0 } = self.get(index) {
16191622
debug_assert!(value.is_deterministic());
16201623
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
16211624
}
@@ -1654,7 +1657,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16541657
let place =
16551658
Place { local, projection: self.tcx.mk_place_elems(projection.as_slice()) };
16561659
return Some(place);
1657-
} else if let Value::Projection(pointer, proj) = *self.get(index)
1660+
} else if let Value::Projection(pointer, proj) = self.get(index)
16581661
&& (allow_complex_projection || proj.is_stable_offset())
16591662
&& let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc)
16601663
{
@@ -1677,7 +1680,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16771680
}
16781681
}
16791682

1680-
impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1683+
impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
16811684
fn tcx(&self) -> TyCtxt<'tcx> {
16821685
self.tcx
16831686
}

0 commit comments

Comments
 (0)