Skip to content

Commit ce21b6b

Browse files
committed
Simplify project.
1 parent 8216f59 commit ce21b6b

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
@@ -812,81 +812,80 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
812812
proj: ProjectionElem<VnIndex, Ty<'tcx>>,
813813
) -> Option<(PlaceTy<'tcx>, VnIndex)> {
814814
let projection_ty = place_ty.projection_ty(self.tcx, proj);
815-
let proj = match proj {
816-
ProjectionElem::Deref => {
817-
if let Some(Mutability::Not) = place_ty.ty.ref_mutability()
815+
let proj = proj.try_map(Some, |_| ())?;
816+
817+
if let ProjectionElem::Deref = proj
818+
&& !(
819+
// An immutable borrow `_x` always points to the same value for the
820+
// lifetime of the borrow, so we can merge all instances of `*_x`.
821+
place_ty.ty.ref_mutability() == Some(Mutability::Not)
818822
&& projection_ty.ty.is_freeze(self.tcx, self.typing_env())
819-
{
820-
if let Value::Address { base, projection, .. } = self.get(value)
821-
&& let Some(value) = self.dereference_address(base, projection)
822-
{
823-
return Some((projection_ty, value));
824-
}
823+
)
824+
{
825+
return None;
826+
}
825827

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

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

0 commit comments

Comments
 (0)