Skip to content

Commit ac70dc8

Browse files
committed
Introduce Value::RawPtr as it behaves differently from other aggregates.
1 parent fba4177 commit ac70dc8

File tree

1 file changed

+67
-55
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+67
-55
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 67 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,6 @@ enum AggregateTy<'tcx> {
163163
Array,
164164
Tuple,
165165
Def(DefId, ty::GenericArgsRef<'tcx>),
166-
RawPtr {
167-
/// Needed for cast propagation.
168-
data_pointer_ty: Ty<'tcx>,
169-
/// The data pointer can be anything thin, so doesn't determine the output.
170-
output_pointer_ty: Ty<'tcx>,
171-
},
172166
}
173167

174168
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -194,6 +188,17 @@ enum Value<'tcx> {
194188
/// An aggregate value, either tuple/closure/struct/enum.
195189
/// This does not contain unions, as we cannot reason with the value.
196190
Aggregate(AggregateTy<'tcx>, VariantIdx, Vec<VnIndex>),
191+
/// A raw pointer aggregate built from a thin pointer and metadata.
192+
RawPtr {
193+
/// Thin pointer component. This is field 0 in MIR.
194+
pointer: VnIndex,
195+
/// Metadata component. This is field 1 in MIR.
196+
metadata: VnIndex,
197+
/// Needed for cast propagation.
198+
data_pointer_ty: Ty<'tcx>,
199+
/// The data pointer can be anything thin, so doesn't determine the output.
200+
output_pointer_ty: Ty<'tcx>,
201+
},
197202
/// This corresponds to a `[value; count]` expression.
198203
Repeat(VnIndex, ty::Const<'tcx>),
199204
/// The address of a place.
@@ -402,22 +407,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
402407
AggregateTy::Def(def_id, args) => {
403408
self.tcx.type_of(def_id).instantiate(self.tcx, args)
404409
}
405-
AggregateTy::RawPtr { output_pointer_ty, .. } => output_pointer_ty,
406410
};
407411
let variant = if ty.is_enum() { Some(variant) } else { None };
408412
let ty = self.ecx.layout_of(ty).ok()?;
409413
if ty.is_zst() {
410414
ImmTy::uninit(ty).into()
411-
} else if matches!(kind, AggregateTy::RawPtr { .. }) {
412-
// Pointers don't have fields, so don't `project_field` them.
413-
let data = self.ecx.read_pointer(fields[0]).discard_err()?;
414-
let meta = if fields[1].layout.is_zst() {
415-
MemPlaceMeta::None
416-
} else {
417-
MemPlaceMeta::Meta(self.ecx.read_scalar(fields[1]).discard_err()?)
418-
};
419-
let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx);
420-
ImmTy::from_immediate(ptr_imm, ty).into()
421415
} else if matches!(
422416
ty.backend_repr,
423417
BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)
@@ -446,6 +440,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
446440
return None;
447441
}
448442
}
443+
RawPtr { pointer, metadata, output_pointer_ty, data_pointer_ty: _ } => {
444+
let pointer = self.evaluated[pointer].as_ref()?;
445+
let metadata = self.evaluated[metadata].as_ref()?;
446+
let output_pointer_ty = self.ecx.layout_of(output_pointer_ty).ok()?;
447+
debug_assert!(!output_pointer_ty.is_zst());
448+
449+
// Pointers don't have fields, so don't `project_field` them.
450+
let data = self.ecx.read_pointer(pointer).discard_err()?;
451+
let meta = if metadata.layout.is_zst() {
452+
MemPlaceMeta::None
453+
} else {
454+
MemPlaceMeta::Meta(self.ecx.read_scalar(metadata).discard_err()?)
455+
};
456+
let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx);
457+
ImmTy::from_immediate(ptr_imm, output_pointer_ty).into()
458+
}
449459

450460
Projection(base, elem) => {
451461
let value = self.evaluated[base].as_ref()?;
@@ -1026,7 +1036,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10261036
}
10271037
}
10281038

1029-
let (mut ty, variant_index) = match *kind {
1039+
let fields: Vec<_> = field_ops
1040+
.iter_mut()
1041+
.map(|op| self.simplify_operand(op, location).unwrap_or_else(|| self.new_opaque()))
1042+
.collect();
1043+
1044+
let (ty, variant_index) = match *kind {
10301045
AggregateKind::Array(..) => {
10311046
assert!(!field_ops.is_empty());
10321047
(AggregateTy::Array, FIRST_VARIANT)
@@ -1045,41 +1060,41 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10451060
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
10461061
AggregateKind::RawPtr(pointee_ty, mtbl) => {
10471062
assert_eq!(field_ops.len(), 2);
1048-
let data_pointer_ty = field_ops[FieldIdx::ZERO].ty(self.local_decls, self.tcx);
1063+
let mut data_pointer_ty = field_ops[FieldIdx::ZERO].ty(self.local_decls, self.tcx);
10491064
let output_pointer_ty = Ty::new_ptr(self.tcx, pointee_ty, mtbl);
1050-
(AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty }, FIRST_VARIANT)
1051-
}
1052-
};
1053-
1054-
let mut fields: Vec<_> = field_ops
1055-
.iter_mut()
1056-
.map(|op| self.simplify_operand(op, location).unwrap_or_else(|| self.new_opaque()))
1057-
.collect();
10581065

1059-
if let AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty } = &mut ty {
1060-
let mut was_updated = false;
1066+
let [mut pointer, metadata] = fields.try_into().unwrap();
1067+
1068+
// Any thin pointer of matching mutability is fine as the data pointer.
1069+
let mut was_updated = false;
1070+
while let Value::Cast {
1071+
kind: CastKind::PtrToPtr,
1072+
value: cast_value,
1073+
from: cast_from,
1074+
to: _,
1075+
} = self.get(pointer)
1076+
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind()
1077+
&& let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind()
1078+
&& from_mtbl == output_mtbl
1079+
&& from_pointee_ty.is_sized(self.tcx, self.typing_env())
1080+
{
1081+
pointer = *cast_value;
1082+
data_pointer_ty = *cast_from;
1083+
was_updated = true;
1084+
}
10611085

1062-
// Any thin pointer of matching mutability is fine as the data pointer.
1063-
while let Value::Cast {
1064-
kind: CastKind::PtrToPtr,
1065-
value: cast_value,
1066-
from: cast_from,
1067-
to: _,
1068-
} = self.get(fields[0])
1069-
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind()
1070-
&& let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind()
1071-
&& from_mtbl == output_mtbl
1072-
&& from_pointee_ty.is_sized(self.tcx, self.typing_env())
1073-
{
1074-
fields[0] = *cast_value;
1075-
*data_pointer_ty = *cast_from;
1076-
was_updated = true;
1077-
}
1086+
if was_updated && let Some(op) = self.try_as_operand(pointer, location) {
1087+
field_ops[FieldIdx::ZERO] = op;
1088+
}
10781089

1079-
if was_updated && let Some(op) = self.try_as_operand(fields[0], location) {
1080-
field_ops[FieldIdx::ZERO] = op;
1090+
return Some(self.insert(Value::RawPtr {
1091+
output_pointer_ty,
1092+
data_pointer_ty,
1093+
pointer,
1094+
metadata,
1095+
}));
10811096
}
1082-
}
1097+
};
10831098

10841099
if let AggregateTy::Array = ty
10851100
&& fields.len() > 4
@@ -1165,9 +1180,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11651180
(UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
11661181
Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
11671182
}
1168-
(UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
1169-
return Some(fields[1]);
1170-
}
1183+
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) => return Some(*metadata),
11711184
// We have an unsizing cast, which assigns the length to wide pointer metadata.
11721185
(
11731186
UnOp::PtrMetadata,
@@ -1399,16 +1412,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13991412
// If a cast just casts away the metadata again, then we can get it by
14001413
// casting the original thin pointer passed to `from_raw_parts`
14011414
if let PtrToPtr = kind
1402-
&& let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) =
1403-
self.get(value)
1415+
&& let Value::RawPtr { data_pointer_ty, pointer, .. } = self.get(value)
14041416
&& let ty::RawPtr(to_pointee, _) = to.kind()
14051417
&& to_pointee.is_sized(self.tcx, self.typing_env())
14061418
{
14071419
from = *data_pointer_ty;
1408-
value = fields[0];
1420+
value = *pointer;
14091421
was_updated_this_iteration = true;
14101422
if *data_pointer_ty == to {
1411-
return Some(fields[0]);
1423+
return Some(*pointer);
14121424
}
14131425
}
14141426

0 commit comments

Comments
 (0)