@@ -896,18 +896,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
896896
897897 fn simplify_aggregate_to_copy (
898898 & mut self ,
899- lhs : & Place < ' tcx > ,
900- rvalue : & mut Rvalue < ' tcx > ,
901- location : Location ,
902- fields : & [ VnIndex ] ,
899+ ty : Ty < ' tcx > ,
903900 variant_index : VariantIdx ,
901+ fields : & [ VnIndex ] ,
904902 ) -> Option < VnIndex > {
905- let Some ( & first_field) = fields. first ( ) else {
906- return None ;
907- } ;
908- let Value :: Projection ( copy_from_value, _) = * self . get ( first_field) else {
909- return None ;
910- } ;
903+ let Some ( & first_field) = fields. first ( ) else { return None } ;
904+ let Value :: Projection ( copy_from_value, _) = * self . get ( first_field) else { return None } ;
905+
911906 // All fields must correspond one-to-one and come from the same aggregate value.
912907 if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
913908 if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = * self . get ( v)
@@ -934,21 +929,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
934929 }
935930 }
936931
937- // Allow introducing places with non-constant offsets, as those are still better than
938- // reconstructing an aggregate.
939- if self . ty ( copy_from_local_value) == rvalue. ty ( self . local_decls , self . tcx )
940- && let Some ( place) = self . try_as_place ( copy_from_local_value, location, true )
941- {
942- // Avoid creating `*a = copy (*b)`, as they might be aliases resulting in overlapping assignments.
943- // FIXME: This also avoids any kind of projection, not just derefs. We can add allowed projections.
944- if lhs. as_local ( ) . is_some ( ) {
945- self . reused_locals . insert ( place. local ) ;
946- * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
947- }
948- return Some ( copy_from_local_value) ;
949- }
950-
951- None
932+ // Both must be variants of the same type.
933+ if self . ty ( copy_from_local_value) == ty { Some ( copy_from_local_value) } else { None }
952934 }
953935
954936 fn simplify_aggregate (
@@ -1035,9 +1017,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10351017 return Some ( self . insert ( ty, Value :: Repeat ( first, len) ) ) ;
10361018 }
10371019
1038- if let Some ( value) =
1039- self . simplify_aggregate_to_copy ( lhs, rvalue, location, & fields, variant_index)
1040- {
1020+ if let Some ( value) = self . simplify_aggregate_to_copy ( ty, variant_index, & fields) {
1021+ // Allow introducing places with non-constant offsets, as those are still better than
1022+ // reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be
1023+ // aliases resulting in overlapping assignments.
1024+ let allow_complex_projection =
1025+ lhs. projection [ ..] . iter ( ) . all ( PlaceElem :: is_stable_offset) ;
1026+ if let Some ( place) = self . try_as_place ( value, location, allow_complex_projection) {
1027+ self . reused_locals . insert ( place. local ) ;
1028+ * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
1029+ }
10411030 return Some ( value) ;
10421031 }
10431032
0 commit comments