Skip to content

Commit 5751d5d

Browse files
committed
Make Value Copy by arena-allocating vectors.
1 parent ea9b64d commit 5751d5d

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
{
@@ -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
{
@@ -857,7 +863,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
857863
fn simplify_discriminant(&mut self, place: VnIndex) -> Option<VnIndex> {
858864
let enum_ty = self.ty(place);
859865
if enum_ty.is_enum()
860-
&& let Value::Aggregate(variant, _) = *self.get(place)
866+
&& let Value::Aggregate(variant, _) = self.get(place)
861867
{
862868
let discr = self.ecx.discriminant_for_variant(enum_ty, variant).discard_err()?;
863869
return Some(self.insert_scalar(discr.layout.ty, discr.to_scalar()));
@@ -893,12 +899,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
893899
let Some(&first_field) = fields.first() else {
894900
return None;
895901
};
896-
let Value::Projection(copy_from_value, _) = *self.get(first_field) else {
902+
let Value::Projection(copy_from_value, _) = self.get(first_field) else {
897903
return None;
898904
};
899905
// All fields must correspond one-to-one and come from the same aggregate value.
900906
if fields.iter().enumerate().any(|(index, &v)| {
901-
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = *self.get(v)
907+
if let Value::Projection(pointer, ProjectionElem::Field(from_index, _)) = self.get(v)
902908
&& copy_from_value == pointer
903909
&& from_index.index() == index
904910
{
@@ -910,7 +916,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
910916
}
911917

912918
let mut copy_from_local_value = copy_from_value;
913-
if let Value::Projection(pointer, proj) = *self.get(copy_from_value)
919+
if let Value::Projection(pointer, proj) = self.get(copy_from_value)
914920
&& let ProjectionElem::Downcast(_, read_variant) = proj
915921
{
916922
if variant_index == read_variant {
@@ -968,13 +974,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
968974
}
969975
}
970976

971-
let fields: Vec<_> = field_ops
972-
.iter_mut()
973-
.map(|op| {
974-
self.simplify_operand(op, location)
975-
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
976-
})
977-
.collect();
977+
let fields = self.arena.alloc_from_iter(field_ops.iter_mut().map(|op| {
978+
self.simplify_operand(op, location)
979+
.unwrap_or_else(|| self.new_opaque(op.ty(self.local_decls, self.tcx)))
980+
}));
978981

979982
let variant_index = match *kind {
980983
AggregateKind::Array(..) | AggregateKind::Tuple => {
@@ -995,12 +998,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
995998
let mut was_updated = false;
996999
while let Value::Cast { kind: CastKind::PtrToPtr, value: cast_value } =
9971000
self.get(pointer)
998-
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(*cast_value).kind()
1001+
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = self.ty(cast_value).kind()
9991002
&& let ty::RawPtr(_, output_mtbl) = ty.kind()
10001003
&& from_mtbl == output_mtbl
10011004
&& from_pointee_ty.is_sized(self.tcx, self.typing_env())
10021005
{
1003-
pointer = *cast_value;
1006+
pointer = cast_value;
10041007
was_updated = true;
10051008
}
10061009

@@ -1058,9 +1061,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10581061
// To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
10591062
// it's fine to get a projection as the type.
10601063
Value::Cast { kind: CastKind::PtrToPtr, value: inner }
1061-
if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) =>
1064+
if self.pointers_have_same_metadata(self.ty(inner), arg_ty) =>
10621065
{
1063-
arg_index = *inner;
1066+
arg_index = inner;
10641067
was_updated = true;
10651068
continue;
10661069
}
@@ -1087,15 +1090,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10871090
}
10881091

10891092
let value = match (op, self.get(arg_index)) {
1090-
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(*inner),
1091-
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(*inner),
1093+
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) => return Some(inner),
1094+
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) => return Some(inner),
10921095
(UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => {
1093-
Value::BinaryOp(BinOp::Ne, *lhs, *rhs)
1096+
Value::BinaryOp(BinOp::Ne, lhs, rhs)
10941097
}
10951098
(UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
1096-
Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
1099+
Value::BinaryOp(BinOp::Eq, lhs, rhs)
10971100
}
1098-
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(*metadata),
1101+
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(metadata),
10991102
// We have an unsizing cast, which assigns the length to wide pointer metadata.
11001103
(
11011104
UnOp::PtrMetadata,
@@ -1104,7 +1107,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11041107
value: inner,
11051108
},
11061109
) if let ty::Slice(..) = arg_ty.builtin_deref(true).unwrap().kind()
1107-
&& let ty::Array(_, len) = self.ty(*inner).builtin_deref(true).unwrap().kind() =>
1110+
&& let ty::Array(_, len) = self.ty(inner).builtin_deref(true).unwrap().kind() =>
11081111
{
11091112
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len)));
11101113
}
@@ -1137,12 +1140,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11371140
&& lhs_ty.is_any_ptr()
11381141
&& let Value::Cast { kind: CastKind::PtrToPtr, value: lhs_value } = self.get(lhs)
11391142
&& let Value::Cast { kind: CastKind::PtrToPtr, value: rhs_value } = self.get(rhs)
1140-
&& let lhs_from = self.ty(*lhs_value)
1141-
&& lhs_from == self.ty(*rhs_value)
1143+
&& let lhs_from = self.ty(lhs_value)
1144+
&& lhs_from == self.ty(rhs_value)
11421145
&& self.pointers_have_same_metadata(lhs_from, lhs_ty)
11431146
{
1144-
lhs = *lhs_value;
1145-
rhs = *rhs_value;
1147+
lhs = lhs_value;
1148+
rhs = rhs_value;
11461149
if let Some(lhs_op) = self.try_as_operand(lhs, location)
11471150
&& let Some(rhs_op) = self.try_as_operand(rhs, location)
11481151
{
@@ -1276,7 +1279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12761279
if op.is_overflowing() {
12771280
let ty = Ty::new_tup(self.tcx, &[self.ty(result), self.tcx.types.bool]);
12781281
let false_val = self.insert_bool(false);
1279-
Some(self.insert_tuple(ty, vec![result, false_val]))
1282+
Some(self.insert_tuple(ty, &[result, false_val]))
12801283
} else {
12811284
Some(result)
12821285
}
@@ -1329,11 +1332,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13291332
&& let ty::RawPtr(to_pointee, _) = to.kind()
13301333
&& to_pointee.is_sized(self.tcx, self.typing_env())
13311334
{
1332-
from = self.ty(*pointer);
1333-
value = *pointer;
1335+
from = self.ty(pointer);
1336+
value = pointer;
13341337
was_updated_this_iteration = true;
13351338
if from == to {
1336-
return Some(*pointer);
1339+
return Some(pointer);
13371340
}
13381341
}
13391342

@@ -1342,7 +1345,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13421345
if let Transmute = kind
13431346
&& let Value::Aggregate(variant_idx, field_values) = self.get(value)
13441347
&& let Some((field_idx, field_ty)) =
1345-
self.value_is_all_in_one_field(from, *variant_idx)
1348+
self.value_is_all_in_one_field(from, variant_idx)
13461349
{
13471350
from = field_ty;
13481351
value = field_values[field_idx.as_usize()];
@@ -1353,7 +1356,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13531356
}
13541357

13551358
// Various cast-then-cast cases can be simplified.
1356-
if let Value::Cast { kind: inner_kind, value: inner_value } = *self.get(value) {
1359+
if let Value::Cast { kind: inner_kind, value: inner_value } = self.get(value) {
13571360
let inner_from = self.ty(inner_value);
13581361
let new_kind = match (inner_kind, kind) {
13591362
// Even if there's a narrowing cast in here that's fine, because
@@ -1427,7 +1430,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
14271430
// We have an unsizing cast, which assigns the length to wide pointer metadata.
14281431
if let Value::Cast { kind, value: from } = self.get(inner)
14291432
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
1430-
&& let Some(from) = self.ty(*from).builtin_deref(true)
1433+
&& let Some(from) = self.ty(from).builtin_deref(true)
14311434
&& let ty::Array(_, len) = from.kind()
14321435
&& let Some(to) = self.ty(inner).builtin_deref(true)
14331436
&& let ty::Slice(..) = to.kind()
@@ -1585,7 +1588,7 @@ fn op_to_prop_const<'tcx>(
15851588
None
15861589
}
15871590

1588-
impl<'tcx> VnState<'_, 'tcx> {
1591+
impl<'tcx> VnState<'_, '_, 'tcx> {
15891592
/// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds,
15901593
/// returns that result as an [`Operand`].
15911594
fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option<Operand<'tcx>> {
@@ -1604,7 +1607,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16041607
// This was already constant in MIR, do not change it. If the constant is not
16051608
// deterministic, adding an additional mention of it in MIR will not give the same value as
16061609
// the former mention.
1607-
if let Value::Constant { value, disambiguator: 0 } = *self.get(index) {
1610+
if let Value::Constant { value, disambiguator: 0 } = self.get(index) {
16081611
debug_assert!(value.is_deterministic());
16091612
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
16101613
}
@@ -1643,7 +1646,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16431646
let place =
16441647
Place { local, projection: self.tcx.mk_place_elems(projection.as_slice()) };
16451648
return Some(place);
1646-
} else if let Value::Projection(pointer, proj) = *self.get(index)
1649+
} else if let Value::Projection(pointer, proj) = self.get(index)
16471650
&& (allow_complex_projection || proj.is_stable_offset())
16481651
&& let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc)
16491652
{
@@ -1666,7 +1669,7 @@ impl<'tcx> VnState<'_, 'tcx> {
16661669
}
16671670
}
16681671

1669-
impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1672+
impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
16701673
fn tcx(&self) -> TyCtxt<'tcx> {
16711674
self.tcx
16721675
}

0 commit comments

Comments
 (0)