Skip to content

Commit 8d9586d

Browse files
committed
Simplify project.
1 parent d5d8bf1 commit 8d9586d

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

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

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

0 commit comments

Comments
 (0)