@@ -896,18 +896,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
896
896
897
897
fn simplify_aggregate_to_copy (
898
898
& mut self ,
899
- lhs : & Place < ' tcx > ,
900
- rvalue : & mut Rvalue < ' tcx > ,
901
- location : Location ,
902
- fields : & [ VnIndex ] ,
899
+ ty : Ty < ' tcx > ,
903
900
variant_index : VariantIdx ,
901
+ fields : & [ VnIndex ] ,
904
902
) -> 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
+
911
906
// All fields must correspond one-to-one and come from the same aggregate value.
912
907
if fields. iter ( ) . enumerate ( ) . any ( |( index, & v) | {
913
908
if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) = * self . get ( v)
@@ -934,21 +929,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
934
929
}
935
930
}
936
931
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 }
952
934
}
953
935
954
936
fn simplify_aggregate (
@@ -1035,9 +1017,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1035
1017
return Some ( self . insert ( ty, Value :: Repeat ( first, len) ) ) ;
1036
1018
}
1037
1019
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
+ }
1041
1030
return Some ( value) ;
1042
1031
}
1043
1032
0 commit comments