@@ -962,18 +962,13 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
962962
963963 fn simplify_aggregate_to_copy (
964964 & mut self ,
965- lhs : & Place < ' tcx > ,
966- rvalue : & mut Rvalue < ' tcx > ,
967- location : Location ,
968- fields : & [ VnIndex ] ,
965+ ty : Ty < ' tcx > ,
969966 variant_index : VariantIdx ,
967+ fields : & [ VnIndex ] ,
970968 ) -> Option < VnIndex > {
971- let Some ( & first_field) = fields. first ( ) else {
972- return None ;
973- } ;
974- let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else {
975- return None ;
976- } ;
969+ let Some ( & first_field) = fields. first ( ) else { return None } ;
970+ let Value :: Projection ( copy_from_value, _) = self . get ( first_field) else { return None } ;
971+
977972 // All fields must correspond one-to-one and come from the same aggregate value.
978973 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
979974 if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = self . get ( v)
@@ -1000,21 +995,8 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
1000995 }
1001996 }
1002997
1003- // Allow introducing places with non-constant offsets, as those are still better than
1004- // reconstructing an aggregate.
1005- if self . ty ( copy_from_local_value) == rvalue. ty ( self . local_decls , self . tcx )
1006- && let Some ( place) = self . try_as_place ( copy_from_local_value, location, true )
1007- {
1008- // Avoid creating `*a = copy (*b)`, as they might be aliases resulting in overlapping assignments.
1009- // FIXME: This also avoids any kind of projection, not just derefs. We can add allowed projections.
1010- if lhs. as_local ( ) . is_some ( ) {
1011- self . reused_locals . insert ( place. local ) ;
1012- * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
1013- }
1014- return Some ( copy_from_local_value) ;
1015- }
1016-
1017- None
998+ // Both must be variants of the same type.
999+ if self . ty ( copy_from_local_value) == ty { Some ( copy_from_local_value) } else { None }
10181000 }
10191001
10201002 fn simplify_aggregate (
@@ -1098,9 +1080,16 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
10981080 }
10991081 }
11001082
1101- if let Some ( value) =
1102- self . simplify_aggregate_to_copy ( lhs, rvalue, location, & fields, variant_index)
1103- {
1083+ if let Some ( value) = self . simplify_aggregate_to_copy ( ty, variant_index, & fields) {
1084+ // Allow introducing places with non-constant offsets, as those are still better than
1085+ // reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be
1086+ // aliases resulting in overlapping assignments.
1087+ let allow_complex_projection =
1088+ lhs. projection [ ..] . iter ( ) . all ( PlaceElem :: is_stable_offset) ;
1089+ if let Some ( place) = self . try_as_place ( value, location, allow_complex_projection) {
1090+ self . reused_locals . insert ( place. local ) ;
1091+ * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
1092+ }
11041093 return Some ( value) ;
11051094 }
11061095
0 commit comments