Skip to content

Commit c08d467

Browse files
committed
Make Value Copy by arena-allocating vectors.
1 parent b50f345 commit c08d467

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.
@@ -213,7 +216,7 @@ enum Value<'tcx> {
213216
},
214217
}
215218

216-
struct VnState<'body, 'tcx> {
219+
struct VnState<'body, 'a, 'tcx> {
217220
tcx: TyCtxt<'tcx>,
218221
ecx: InterpCx<'tcx, DummyMachine>,
219222
local_decls: &'body LocalDecls<'tcx>,
@@ -223,7 +226,7 @@ struct VnState<'body, 'tcx> {
223226
/// Locals that are assigned that value.
224227
// This vector does not hold all the values of `VnIndex` that we create.
225228
rev_locals: IndexVec<VnIndex, SmallVec<[Local; 1]>>,
226-
values: FxIndexSet<(Value<'tcx>, Ty<'tcx>)>,
229+
values: FxIndexSet<(Value<'a, 'tcx>, Ty<'tcx>)>,
227230
/// Values evaluated as constants if possible.
228231
evaluated: IndexVec<VnIndex, Option<OpTy<'tcx>>>,
229232
/// Counter to generate different values.
@@ -233,16 +236,18 @@ struct VnState<'body, 'tcx> {
233236
ssa: &'body SsaLocals,
234237
dominators: Dominators<BasicBlock>,
235238
reused_locals: DenseBitSet<Local>,
239+
arena: &'a DroplessArena,
236240
}
237241

238-
impl<'body, 'tcx> VnState<'body, 'tcx> {
242+
impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
239243
fn new(
240244
tcx: TyCtxt<'tcx>,
241245
body: &Body<'tcx>,
242246
typing_env: ty::TypingEnv<'tcx>,
243247
ssa: &'body SsaLocals,
244248
dominators: Dominators<BasicBlock>,
245249
local_decls: &'body LocalDecls<'tcx>,
250+
arena: &'a DroplessArena,
246251
) -> Self {
247252
// Compute a rough estimate of the number of values in the body from the number of
248253
// statements. This is meant to reduce the number of allocations, but it's all right if
@@ -265,6 +270,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
265270
ssa,
266271
dominators,
267272
reused_locals: DenseBitSet::new_empty(local_decls.len()),
273+
arena,
268274
}
269275
}
270276

@@ -273,7 +279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
273279
}
274280

275281
#[instrument(level = "trace", skip(self), ret)]
276-
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'tcx>) -> VnIndex {
282+
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'a, 'tcx>) -> VnIndex {
277283
let (index, new) = self.values.insert_full((value, ty));
278284
let index = VnIndex::from_usize(index);
279285
if new {
@@ -316,8 +322,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
316322
}
317323

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

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

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

369375
fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex {
@@ -389,7 +395,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
389395
} else {
390396
return None;
391397
};
392-
let op = match *self.get(value) {
398+
let op = match self.get(value) {
393399
_ if ty.is_zst() => ImmTy::uninit(ty).into(),
394400

395401
Opaque(_) => return None,
@@ -609,7 +615,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
609615
if let Value::Aggregate(_, fields) = self.get(value) {
610616
return Some((projection_ty, fields[f.as_usize()]));
611617
} else if let Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)) = self.get(value)
612-
&& let Value::Aggregate(written_variant, fields) = self.get(*outer_value)
618+
&& let Value::Aggregate(written_variant, fields) = self.get(outer_value)
613619
// This pass is not aware of control-flow, so we do not know whether the
614620
// replacement we are doing is actually reachable. We could be in any arm of
615621
// ```
@@ -634,15 +640,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
634640
ProjectionElem::Index(idx) => {
635641
if let Value::Repeat(inner, _) = self.get(value) {
636642
*from_non_ssa_index |= self.locals[idx].is_none();
637-
return Some((projection_ty, *inner));
643+
return Some((projection_ty, inner));
638644
}
639645
let idx = self.locals[idx]?;
640646
ProjectionElem::Index(idx)
641647
}
642648
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
643649
match self.get(value) {
644650
Value::Repeat(inner, _) => {
645-
return Some((projection_ty, *inner));
651+
return Some((projection_ty, inner));
646652
}
647653
Value::Aggregate(_, operands) => {
648654
let offset = if from_end {
@@ -732,8 +738,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
732738
let mut place_ty = PlaceTy::from_ty(self.local_decls[place.local].ty);
733739
let mut from_non_ssa_index = false;
734740
for (index, proj) in place.projection.iter().enumerate() {
735-
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
736-
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
741+
if let Value::Projection(pointer, ProjectionElem::Deref) = self.get(value)
742+
&& let Value::Address { place: mut pointee, kind, .. } = self.get(pointer)
737743
&& let AddressKind::Ref(BorrowKind::Shared) = kind
738744
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
739745
{
@@ -756,8 +762,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
756762
(place_ty, value) = self.project(place_ty, value, proj, &mut from_non_ssa_index)?;
757763
}
758764

759-
if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
760-
&& let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
765+
if let Value::Projection(pointer, ProjectionElem::Deref) = self.get(value)
766+
&& let Value::Address { place: mut pointee, kind, .. } = self.get(pointer)
761767
&& let AddressKind::Ref(BorrowKind::Shared) = kind
762768
&& let Some(v) = self.simplify_place_value(&mut pointee, location)
763769
{
@@ -869,7 +875,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
869875
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
870876
let enum_ty = self.ty(place);
871877
if enum_ty.is_enum()
872-
&& let Value::Aggregate(variant, _) = *self.get(place)
878+
&& let Value::Aggregate(variant, _) = self.get(place)
873879
{
874880
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).discard_err()?;
875881
return Some(self.insert_scalar(discr.layout.ty, discr.to_scalar()));
@@ -901,11 +907,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
901907
fields: &[VnIndex],
902908
) -> Option<VnIndex> {
903909
let Some(&first_field) = fields.first() else { return None };
904-
let Value::Projection(copy_from_value, _) = *self.get(first_field) else { return None };
910+
let Value::Projection(copy_from_value, _) = self.get(first_field) else { return None };
905911

906912
// All fields must correspond one-to-one and come from the same aggregate value.
907913
if fields.iter().enumerate().any(|(index, &v)| {
908-
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = *self.get(v)
914+
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = self.get(v)
909915
&& copy_from_value == pointer
910916
&& from_index.index() == index
911917
{
@@ -917,7 +923,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
917923
}
918924

919925
let mut copy_from_local_value = copy_from_value;
920-
if let Value::Projection(pointer, proj) = *self.get(copy_from_value)
926+
if let Value::Projection(pointer, proj) = self.get(copy_from_value)
921927
&& let ProjectionElem::Downcast(_, read_variant) = proj
922928
{
923929
if variant_index == read_variant {
@@ -962,13 +968,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
962968
}
963969
}
964970

965-
let fields: Vec<_> = field_ops
966-
.iter_mut()
967-
.map(|op| {
968-
self.simplify_operand(op, location)
969-
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
970-
})
971-
.collect();
971+
let fields = self.arena.alloc_from_iter(field_ops.iter_mut().map(|op| {
972+
self.simplify_operand(op, location)
973+
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
974+
}));
972975

973976
let variant_index = match *kind {
974977
AggregateKind::Array(..) | AggregateKind::Tuple => {
@@ -989,12 +992,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
989992
let mut was_updated = false;
990993
while let Value::Cast { kind: CastKind::PtrToPtr, value: cast_value } =
991994
self.get(pointer)
992-
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(*cast_value).kind()
995+
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(cast_value).kind()
993996
&& let ty::RawPtr(_, output_mtbl) = ty.kind()
994997
&& from_mtbl == output_mtbl
995998
&& from_pointee_ty.is_sized(self.tcx, self.typing_env())
996999
{
997-
pointer = *cast_value;
1000+
pointer = cast_value;
9981001
was_updated = true;
9991002
}
10001003

@@ -1059,9 +1062,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10591062
// To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
10601063
// it's fine to get a projection as the type.
10611064
Value::Cast { kind: CastKind::PtrToPtr, value: inner }
1062-
if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) =>
1065+
if self.pointers_have_same_metadata(self.ty(inner), arg_ty) =>
10631066
{
1064-
arg_index = *inner;
1067+
arg_index = inner;
10651068
was_updated = true;
10661069
continue;
10671070
}
@@ -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
@@ -1428,7 +1431,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
14281431
// We have an unsizing cast, which assigns the length to wide pointer metadata.
14291432
if let Value::Cast { kind, value: from } = self.get(inner)
14301433
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
1431-
&& let Some(from) = self.ty(*from).builtin_deref(true)
1434+
&& let Some(from) = self.ty(from).builtin_deref(true)
14321435
&& let ty::Array(_, len) = from.kind()
14331436
&& let Some(to) = self.ty(inner).builtin_deref(true)
14341437
&& let ty::Slice(..) = to.kind()
@@ -1586,7 +1589,7 @@ fn op_to_prop_const<'tcx>(
15861589
None
15871590
}
15881591

1589-
impl<'tcx> VnState<'_, 'tcx> {
1592+
impl<'tcx> VnState<'_, '_, 'tcx> {
15901593
/// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
15911594
/// returns that result as an [`Operand`].
15921595
fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option<Operand<'tcx>> {
@@ -1605,7 +1608,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16051608
// This was already constant in MIR, do not change it. If the constant is not
16061609
// deterministic, adding an additional mention of it in MIR will not give the same value as
16071610
// the former mention.
1608-
if let Value::Constant { value, disambiguator: 0 } = *self.get(index) {
1611+
if let Value::Constant { value, disambiguator: 0 } = self.get(index) {
16091612
debug_assert!(value.is_deterministic());
16101613
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
16111614
}
@@ -1649,7 +1652,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16491652
// If we are here, we failed to find a local, and we already have a `Deref`.
16501653
// Trying to add projections will only result in an ill-formed place.
16511654
return None;
1652-
} else if let Value::Projection(pointer, proj) = *self.get(index)
1655+
} else if let Value::Projection(pointer, proj) = self.get(index)
16531656
&& (allow_complex_projection || proj.is_stable_offset())
16541657
&& let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc)
16551658
{
@@ -1672,7 +1675,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16721675
}
16731676
}
16741677

1675-
impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1678+
impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
16761679
fn tcx(&self) -> TyCtxt<'tcx> {
16771680
self.tcx
16781681
}

0 commit comments

Comments
 (0)