Skip to content

Commit e9f9832

Browse files
committed
Simplify project.
1 parent 5ead463 commit e9f9832

File tree

1 file changed

+68
-69
lines changed
  • compiler/rustc_mir_transform/src

1 file changed

+68
-69
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 68 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -800,81 +800,80 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
800800
proj: ProjectionElem<VnIndex, Ty<'tcx>>,
801801
) -> Option<(PlaceTy<'tcx>, VnIndex)> {
802802
let projection_ty = place_ty.projection_ty(self.tcx, proj);
803-
let proj = match proj {
804-
ProjectionElem::Deref => {
805-
if let Some(Mutability::Not) = place_ty.ty.ref_mutability()
803+
let proj = proj.try_map(Some, |_| ())?;
804+
805+
if let ProjectionElem::Deref = proj
806+
&& !(
807+
// An immutable borrow `_x` always points to the same value for the
808+
// lifetime of the borrow, so we can merge all instances of `*_x`.
809+
place_ty.ty.ref_mutability() == Some(Mutability::Not)
806810
&& projection_ty.ty.is_freeze(self.tcx, self.typing_env())
807-
{
808-
if let Value::Address { base, projection, .. } = self.get(value)
809-
&& let Some(value) = self.dereference_address(base, projection)
810-
{
811-
return Some((projection_ty, value));
812-
}
811+
)
812+
{
813+
return None;
814+
}
813815

814-
// An immutable borrow `_x` always points to the same value for the
815-
// lifetime of the borrow, so we can merge all instances of `*_x`.
816-
return Some((projection_ty, self.insert_deref(projection_ty.ty, value)));
817-
} else {
818-
return None;
819-
}
816+
match (proj, self.get(value)) {
817+
(ProjectionElem::Deref, Value::Address { base, projection, .. })
818+
if let Some(deref) = self.dereference_address(base, projection) =>
819+
{
820+
return Some((projection_ty, deref));
820821
}
821-
ProjectionElem::Downcast(name, index) => ProjectionElem::Downcast(name, index),
822-
ProjectionElem::Field(f, _) => match self.get(value) {
823-
Value::Aggregate(_, fields) => return Some((projection_ty, fields[f.as_usize()])),
824-
Value::Union(active, field) if active == f => return Some((projection_ty, field)),
825-
Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant))
826-
if let Value::Aggregate(written_variant, fields) = self.get(outer_value)
827-
// This pass is not aware of control-flow, so we do not know whether the
828-
// replacement we are doing is actually reachable. We could be in any arm of
829-
// ```
830-
// match Some(x) {
831-
// Some(y) => /* stuff */,
832-
// None => /* other */,
833-
// }
834-
// ```
835-
//
836-
// In surface rust, the current statement would be unreachable.
837-
//
838-
// However, from the reference chapter on enums and RFC 2195,
839-
// accessing the wrong variant is not UB if the enum has repr.
840-
// So it's not impossible for a series of MIR opts to generate
841-
// a downcast to an inactive variant.
842-
&& written_variant == read_variant =>
843-
{
844-
return Some((projection_ty, fields[f.as_usize()]));
845-
}
846-
_ => ProjectionElem::Field(f, ()),
847-
},
848-
ProjectionElem::Index(idx) => {
849-
if let Value::Repeat(inner, _) = self.get(value) {
850-
return Some((projection_ty, inner));
851-
}
852-
ProjectionElem::Index(idx)
822+
(ProjectionElem::Deref, _) => {
823+
return Some((projection_ty, self.insert_deref(projection_ty.ty, value)));
853824
}
854-
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
855-
match self.get(value) {
856-
Value::Repeat(inner, _) => {
857-
return Some((projection_ty, inner));
858-
}
859-
Value::Aggregate(_, operands) => {
860-
let offset = if from_end {
861-
operands.len() - offset as usize
862-
} else {
863-
offset as usize
864-
};
865-
let value = operands.get(offset).copied()?;
866-
return Some((projection_ty, value));
867-
}
868-
_ => {}
869-
};
870-
ProjectionElem::ConstantIndex { offset, min_length, from_end }
825+
(ProjectionElem::Field(f, _), Value::Aggregate(_, fields)) => {
826+
return Some((projection_ty, fields[f.as_usize()]));
871827
}
872-
ProjectionElem::Subslice { from, to, from_end } => {
873-
ProjectionElem::Subslice { from, to, from_end }
828+
(ProjectionElem::Field(f, _), Value::Union(active, field)) if active == f => {
829+
return Some((projection_ty, field));
874830
}
875-
ProjectionElem::OpaqueCast(_) => ProjectionElem::OpaqueCast(()),
876-
ProjectionElem::UnwrapUnsafeBinder(_) => ProjectionElem::UnwrapUnsafeBinder(()),
877-
};
831+
(
832+
ProjectionElem::Field(f, _),
833+
Value::Projection(outer_value, ProjectionElem::Downcast(_, read_variant)),
834+
) if let Value::Aggregate(written_variant, fields) = self.get(outer_value)
835+
// This pass is not aware of control-flow, so we do not know whether the
836+
// replacement we are doing is actually reachable. We could be in any arm of
837+
// ```
838+
// match Some(x) {
839+
// Some(y) => /* stuff */,
840+
// None => /* other */,
841+
// }
842+
// ```
843+
//
844+
// In surface rust, the current statement would be unreachable.
845+
//
846+
// However, from the reference chapter on enums and RFC 2195,
847+
// accessing the wrong variant is not UB if the enum has repr.
848+
// So it's not impossible for a series of MIR opts to generate
849+
// a downcast to an inactive variant.
850+
&& written_variant == read_variant =>
851+
{
852+
return Some((projection_ty, fields[f.as_usize()]));
853+
}
854+
(ProjectionElem::Index(_), Value::Repeat(inner, _)) => {
855+
return Some((projection_ty, inner));
856+
}
857+
(ProjectionElem::ConstantIndex { .. }, Value::Repeat(inner, _)) => {
858+
return Some((projection_ty, inner));
859+
}
860+
(
861+
ProjectionElem::ConstantIndex { offset, from_end: false, .. },
862+
Value::Aggregate(_, operands),
863+
) => {
864+
let value = operands.get(offset as usize).copied()?;
865+
return Some((projection_ty, value));
866+
}
867+
(
868+
ProjectionElem::ConstantIndex { offset, from_end: true, .. },
869+
Value::Aggregate(_, operands),
870+
) => {
871+
let offset = operands.len().checked_sub(offset as usize)?;
872+
let value = operands[offset];
873+
return Some((projection_ty, value));
874+
}
875+
_ => {}
876+
}
878877

879878
let value = self.insert(projection_ty.ty, Value::Projection(value, proj));
880879
Some((projection_ty, value))

0 commit comments

Comments
 (0)