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