@@ -836,6 +836,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
836836 #[instrument(level = "trace", skip(self), ret)]
837837 fn simplify_rvalue(
838838 &mut self,
839+ lhs: &Place<'tcx>,
839840 rvalue: &mut Rvalue<'tcx>,
840841 location: Location,
841842 ) -> Option<VnIndex> {
@@ -855,7 +856,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
855856 Value::Repeat(op, amount)
856857 }
857858 Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
858- Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location),
859+ Rvalue::Aggregate(..) => return self.simplify_aggregate(lhs, rvalue, location),
859860 Rvalue::Ref(_, borrow_kind, ref mut place) => {
860861 self.simplify_place_projection(place, location);
861862 return Some(self.new_pointer(*place, AddressKind::Ref(borrow_kind)));
@@ -943,6 +944,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
943944
944945 fn simplify_aggregate_to_copy(
945946 &mut self,
947+ lhs: &Place<'tcx>,
946948 rvalue: &mut Rvalue<'tcx>,
947949 location: Location,
948950 fields: &[VnIndex],
@@ -982,19 +984,24 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
982984
983985 // Allow introducing places with non-constant offsets, as those are still better than
984986 // reconstructing an aggregate.
985- if let Some(place) = self.try_as_place(copy_from_local_value, location, true) {
986- if rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty {
987+ if let Some(place) = self.try_as_place(copy_from_local_value, location, true)
988+ && rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty
989+ {
990+ // Avoid creating `*a = copy (*b)`, as they might be aliases resulting in overlapping assignments.
991+ // FIXME: This also avoids any kind of projection, not just derefs. We can add allowed projections.
992+ if lhs.as_local().is_some() {
987993 self.reused_locals.insert(place.local);
988994 *rvalue = Rvalue::Use(Operand::Copy(place));
989- return Some(copy_from_local_value);
990995 }
996+ return Some(copy_from_local_value);
991997 }
992998
993999 None
9941000 }
9951001
9961002 fn simplify_aggregate(
9971003 &mut self,
1004+ lhs: &Place<'tcx>,
9981005 rvalue: &mut Rvalue<'tcx>,
9991006 location: Location,
10001007 ) -> Option<VnIndex> {
@@ -1090,7 +1097,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10901097
10911098 if let AggregateTy::Def(_, _) = ty
10921099 && let Some(value) =
1093- self.simplify_aggregate_to_copy(rvalue, location, &fields, variant_index)
1100+ self.simplify_aggregate_to_copy(lhs, rvalue, location, &fields, variant_index)
10941101 {
10951102 return Some(value);
10961103 }
@@ -1765,7 +1772,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
17651772 if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind {
17661773 self.simplify_place_projection(lhs, location);
17671774
1768- let value = self.simplify_rvalue(rvalue, location);
1775+ let value = self.simplify_rvalue(lhs, rvalue, location);
17691776 let value = if let Some(local) = lhs.as_local()
17701777 && self.ssa.is_ssa(local)
17711778 // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark
0 commit comments