Skip to content

Commit 0683fdd

Browse files
committed
Make Value Copy by arena-allocating vectors.
1 parent ce6daf3 commit 0683fdd

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
@@ -89,6 +89,7 @@ use std::borrow::Cow;
8989
use either::Either;
9090
use itertools::Itertools as _;
9191
use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx};
92+
use rustc_arena::DroplessArena;
9293
use rustc_const_eval::const_eval::DummyMachine;
9394
use rustc_const_eval::interpret::{
9495
ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar,
@@ -127,7 +128,9 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
127128
// Clone dominators because we need them while mutating the body.
128129
let dominators = body.basic_blocks.dominators().clone();
129130

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

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

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

214-
struct VnState<'body, 'tcx> {
217+
struct VnState<'body, 'a, 'tcx> {
215218
tcx: TyCtxt<'tcx>,
216219
ecx: InterpCx<'tcx, DummyMachine>,
217220
local_decls: &'body LocalDecls<'tcx>,
@@ -221,7 +224,7 @@ struct VnState<'body, 'tcx> {
221224
/// Locals that are assigned that value.
222225
// This vector does not hold all the values of `VnIndex` that we create.
223226
rev_locals: IndexVec<VnIndex, SmallVec<[Local; 1]>>,
224-
values: FxIndexSet<(Value<'tcx>, Ty<'tcx>)>,
227+
values: FxIndexSet<(Value<'a, 'tcx>, Ty<'tcx>)>,
225228
/// Values evaluated as constants if possible.
226229
evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>,
227230
/// Counter to generate different values.
@@ -231,16 +234,18 @@ struct VnState<'body, 'tcx> {
231234
ssa: &'body SsaLocals,
232235
dominators: Dominators<BasicBlock>,
233236
reused_locals: DenseBitSet<Local>,
237+
arena: &'a DroplessArena,
234238
}
235239

236-
impl<'body, 'tcx> VnState<'body, 'tcx> {
240+
impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
237241
fn new(
238242
tcx: TyCtxt<'tcx>,
239243
body: &Body<'tcx>,
240244
typing_env: ty::TypingEnv<'tcx>,
241245
ssa: &'body SsaLocals,
242246
dominators: Dominators<BasicBlock>,
243247
local_decls: &'body LocalDecls<'tcx>,
248+
arena: &'a DroplessArena,
244249
) -> Self {
245250
// Compute a rough estimate of the number of values in the body from the number of
246251
// statements. This is meant to reduce the number of allocations, but it's all right if
@@ -263,6 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
263268
ssa,
264269
dominators,
265270
reused_locals: DenseBitSet::new_empty(local_decls.len()),
271+
arena,
266272
}
267273
}
268274

@@ -271,7 +277,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
271277
}
272278

273279
#[instrument(level = "trace", skip(self), ret)]
274-
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'tcx>) -> VnIndex {
280+
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'a, 'tcx>) -> VnIndex {
275281
let (index, new) = self.values.insert_full((value, ty));
276282
let index = VnIndex::from_usize(index);
277283
if new {
@@ -314,8 +320,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
314320
}
315321

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

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

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

367373
fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex {
@@ -387,7 +393,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
387393
} else {
388394
return None;
389395
};
390-
let op = match *self.get(value) {
396+
let op = match self.get(value) {
391397
_ if ty.is_zst() => ImmTy::uninit(ty).into(),
392398

393399
Opaque(_) => return None,
@@ -602,7 +608,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
602608
if let Value::Aggregate(_, fields) = self.get(value) {
603609
return Some((projection_ty, fields[f.as_usize()]));
604610
} else if let Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)) = self.get(value)
605-
&& let Value::Aggregate(written_variant, fields) = self.get(*outer_value)
611+
&& let Value::Aggregate(written_variant, fields) = self.get(outer_value)
606612
// This pass is not aware of control-flow, so we do not know whether the
607613
// replacement we are doing is actually reachable. We could be in any arm of
608614
// ```
@@ -627,15 +633,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
627633
ProjectionElem::Index(idx) => {
628634
if let Value::Repeat(inner, _) = self.get(value) {
629635
*from_non_ssa_index |= self.locals[idx].is_none();
630-
return Some((projection_ty, *inner));
636+
return Some((projection_ty, inner));
631637
}
632638
let idx = self.locals[idx]?;
633639
ProjectionElem::Index(idx)
634640
}
635641
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
636642
match self.get(value) {
637643
Value::Repeat(inner, _) => {
638-
return Some((projection_ty, *inner));
644+
return Some((projection_ty, inner));
639645
}
640646
Value::Aggregate(_, operands) => {
641647
let offset = if from_end {
@@ -725,8 +731,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
725731
let mut place_ty = PlaceTy::from_ty(self.local_decls[place.local].ty);
726732
let mut from_non_ssa_index = false;
727733
for (index, proj) in place.projection.iter().enumerate() {
728-
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
729-
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
734+
if let Value::Projection(pointer, ProjectionElem::Deref) = self.get(value)
735+
&& let Value::Address { place: mut pointee, kind, .. } = self.get(pointer)
730736
&& let AddressKind::Ref(BorrowKind::Shared) = kind
731737
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
732738
{
@@ -749,8 +755,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
749755
(place_ty, value) = self.project(place_ty, value, proj, &mut from_non_ssa_index)?;
750756
}
751757

752-
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
753-
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
758+
if let Value::Projection(pointer, ProjectionElem::Deref) = self.get(value)
759+
&& let Value::Address { place: mut pointee, kind, .. } = self.get(pointer)
754760
&& let AddressKind::Ref(BorrowKind::Shared) = kind
755761
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
756762
{
@@ -861,7 +867,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
861867
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
862868
let enum_ty = self.ty(place);
863869
if enum_ty.is_enum()
864-
&& let Value::Aggregate(variant, _) = *self.get(place)
870+
&& let Value::Aggregate(variant, _) = self.get(place)
865871
{
866872
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).discard_err()?;
867873
return Some(self.insert_scalar(discr.layout.ty, discr.to_scalar()));
@@ -893,11 +899,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
893899
fields: &[VnIndex],
894900
) -> Option<VnIndex> {
895901
let Some(&first_field) = fields.first() else { return None };
896-
let Value::Projection(copy_from_value, _) = *self.get(first_field) else { return None };
902+
let Value::Projection(copy_from_value, _) = self.get(first_field) else { return None };
897903

898904
// All fields must correspond one-to-one and come from the same aggregate value.
899905
if fields.iter().enumerate().any(|(index, &v)| {
900-
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = *self.get(v)
906+
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = self.get(v)
901907
&& copy_from_value == pointer
902908
&& from_index.index() == index
903909
{
@@ -909,7 +915,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
909915
}
910916

911917
let mut copy_from_local_value = copy_from_value;
912-
if let Value::Projection(pointer, proj) = *self.get(copy_from_value)
918+
if let Value::Projection(pointer, proj) = self.get(copy_from_value)
913919
&& let ProjectionElem::Downcast(_, read_variant) = proj
914920
{
915921
if variant_index == read_variant {
@@ -954,13 +960,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
954960
}
955961
}
956962

957-
let fields: Vec<_> = field_ops
958-
.iter_mut()
959-
.map(|op| {
960-
self.simplify_operand(op, location)
961-
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
962-
})
963-
.collect();
963+
let fields = self.arena.alloc_from_iter(field_ops.iter_mut().map(|op| {
964+
self.simplify_operand(op, location)
965+
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
966+
}));
964967

965968
let variant_index = match *kind {
966969
AggregateKind::Array(..) | AggregateKind::Tuple => {
@@ -981,12 +984,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
981984
let mut was_updated = false;
982985
while let Value::Cast { kind: CastKind::PtrToPtr, value: cast_value } =
983986
self.get(pointer)
984-
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(*cast_value).kind()
987+
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(cast_value).kind()
985988
&& let ty::RawPtr(_, output_mtbl) = ty.kind()
986989
&& from_mtbl == output_mtbl
987990
&& from_pointee_ty.is_sized(self.tcx, self.typing_env())
988991
{
989-
pointer = *cast_value;
992+
pointer = cast_value;
990993
was_updated = true;
991994
}
992995

@@ -1051,16 +1054,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10511054
// To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
10521055
// it's fine to get a projection as the type.
10531056
Value::Cast { kind: CastKind::PtrToPtr, value: inner }
1054-
if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) =>
1057+
if self.pointers_have_same_metadata(self.ty(inner), arg_ty) =>
10551058
{
1056-
*inner
1059+
inner
10571060
}
10581061

10591062
// We have an unsizing cast, which assigns the length to wide pointer metadata.
10601063
Value::Cast {
10611064
kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _),
10621065
value: from,
1063-
} if let Some(from) = self.ty(*from).builtin_deref(true)
1066+
} if let Some(from) = self.ty(from).builtin_deref(true)
10641067
&& let ty::Array(_, len) = from.kind()
10651068
&& let Some(to) = self.ty(arg_index).builtin_deref(true)
10661069
&& let ty::Slice(..) = to.kind() =>
@@ -1088,15 +1091,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10881091
}
10891092

10901093
let value = match (op, self.get(arg_index)) {
1091-
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner),
1092-
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner),
1094+
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(inner),
1095+
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(inner),
10931096
(UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => {
1094-
Value::BinaryOp(BinOp::Ne, *lhs, *rhs)
1097+
Value::BinaryOp(BinOp::Ne, lhs, rhs)
10951098
}
10961099
(UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
1097-
Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
1100+
Value::BinaryOp(BinOp::Eq, lhs, rhs)
10981101
}
1099-
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(*metadata),
1102+
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(metadata),
11001103
// We have an unsizing cast, which assigns the length to wide pointer metadata.
11011104
(
11021105
UnOp::PtrMetadata,
@@ -1105,7 +1108,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11051108
value: inner,
11061109
},
11071110
) if let ty::Slice(..) = arg_ty.builtin_deref(true).unwrap().kind()
1108-
&& let ty::Array(_, len) = self.ty(*inner).builtin_deref(true).unwrap().kind() =>
1111+
&& let ty::Array(_, len) = self.ty(inner).builtin_deref(true).unwrap().kind() =>
11091112
{
11101113
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
11111114
}
@@ -1138,12 +1141,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11381141
&& lhs_ty.is_any_ptr()
11391142
&& let Value::Cast { kind: CastKind::PtrToPtr, value: lhs_value } = self.get(lhs)
11401143
&& let Value::Cast { kind: CastKind::PtrToPtr, value: rhs_value } = self.get(rhs)
1141-
&& let lhs_from = self.ty(*lhs_value)
1142-
&& lhs_from == self.ty(*rhs_value)
1144+
&& let lhs_from = self.ty(lhs_value)
1145+
&& lhs_from == self.ty(rhs_value)
11431146
&& self.pointers_have_same_metadata(lhs_from, lhs_ty)
11441147
{
1145-
lhs = *lhs_value;
1146-
rhs = *rhs_value;
1148+
lhs = lhs_value;
1149+
rhs = rhs_value;
11471150
if let Some(lhs_op) = self.try_as_operand(lhs, location)
11481151
&& let Some(rhs_op) = self.try_as_operand(rhs, location)
11491152
{
@@ -1277,7 +1280,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12771280
if op.is_overflowing() {
12781281
let ty = Ty::new_tup(self.tcx, &[self.ty(result), self.tcx.types.bool]);
12791282
let false_val = self.insert_bool(false);
1280-
Some(self.insert_tuple(ty, vec![result, false_val]))
1283+
Some(self.insert_tuple(ty, &[result, false_val]))
12811284
} else {
12821285
Some(result)
12831286
}
@@ -1330,11 +1333,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13301333
&& let ty::RawPtr(to_pointee, _) = to.kind()
13311334
&& to_pointee.is_sized(self.tcx, self.typing_env())
13321335
{
1333-
from = self.ty(*pointer);
1334-
value = *pointer;
1336+
from = self.ty(pointer);
1337+
value = pointer;
13351338
was_updated_this_iteration = true;
13361339
if from == to {
1337-
return Some(*pointer);
1340+
return Some(pointer);
13381341
}
13391342
}
13401343

@@ -1343,7 +1346,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13431346
if let Transmute = kind
13441347
&& let Value::Aggregate(variant_idx, field_values) = self.get(value)
13451348
&& let Some((field_idx, field_ty)) =
1346-
self.value_is_all_in_one_field(from, *variant_idx)
1349+
self.value_is_all_in_one_field(from, variant_idx)
13471350
{
13481351
from = field_ty;
13491352
value = field_values[field_idx.as_usize()];
@@ -1354,7 +1357,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13541357
}
13551358

13561359
// Various cast-then-cast cases can be simplified.
1357-
if let Value::Cast { kind: inner_kind, value: inner_value } = *self.get(value) {
1360+
if let Value::Cast { kind: inner_kind, value: inner_value } = self.get(value) {
13581361
let inner_from = self.ty(inner_value);
13591362
let new_kind = match (inner_kind, kind) {
13601363
// Even if there's a narrowing cast in here that's fine, because
@@ -1553,7 +1556,7 @@ fn op_to_prop_const<'tcx>(
15531556
None
15541557
}
15551558

1556-
impl<'tcx> VnState<'_, 'tcx> {
1559+
impl<'tcx> VnState<'_, '_, 'tcx> {
15571560
/// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
15581561
/// returns that result as an [`Operand`].
15591562
fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option<Operand<'tcx>> {
@@ -1572,7 +1575,7 @@ impl<'tcx> VnState<'_, 'tcx> {
15721575
// This was already constant in MIR, do not change it. If the constant is not
15731576
// deterministic, adding an additional mention of it in MIR will not give the same value as
15741577
// the former mention.
1575-
if let Value::Constant { value, disambiguator: 0 } = *self.get(index) {
1578+
if let Value::Constant { value, disambiguator: 0 } = self.get(index) {
15761579
debug_assert!(value.is_deterministic());
15771580
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
15781581
}
@@ -1616,7 +1619,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16161619
// If we are here, we failed to find a local, and we already have a `Deref`.
16171620
// Trying to add projections will only result in an ill-formed place.
16181621
return None;
1619-
} else if let Value::Projection(pointer, proj) = *self.get(index)
1622+
} else if let Value::Projection(pointer, proj) = self.get(index)
16201623
&& (allow_complex_projection || proj.is_stable_offset())
16211624
&& let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc)
16221625
{
@@ -1639,7 +1642,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16391642
}
16401643
}
16411644

1642-
impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1645+
impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
16431646
fn tcx(&self) -> TyCtxt<'tcx> {
16441647
self.tcx
16451648
}

0 commit comments

Comments
 (0)