@@ -863,9 +863,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
863
863
rvalue : & mut Rvalue < ' tcx > ,
864
864
location : Location ,
865
865
) -> Option < VnIndex > {
866
+ let tcx = self . tcx ;
867
+ let rvalue_ty = rvalue. ty ( self . local_decls , tcx) ;
866
868
let Rvalue :: Aggregate ( box ref kind, ref mut field_ops) = * rvalue else { bug ! ( ) } ;
867
869
868
- let tcx = self . tcx ;
869
870
if field_ops. is_empty ( ) {
870
871
let is_zst = match * kind {
871
872
AggregateKind :: Array ( ..)
@@ -880,8 +881,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
880
881
} ;
881
882
882
883
if is_zst {
883
- let ty = rvalue. ty ( self . local_decls , tcx) ;
884
- return self . insert_constant ( Const :: zero_sized ( ty) ) ;
884
+ return self . insert_constant ( Const :: zero_sized ( rvalue_ty) ) ;
885
885
}
886
886
}
887
887
@@ -916,6 +916,60 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
916
916
. collect ( ) ;
917
917
let mut fields = fields?;
918
918
919
+ if let AggregateTy :: Def ( _, _) = & mut ty
920
+ && !fields. is_empty ( )
921
+ {
922
+ let copy_from = if let Value :: Projection ( first_pointer, ProjectionElem :: Field ( _, _) ) =
923
+ * self . get ( fields[ 0 ] )
924
+ {
925
+ let mut copy_from_value = first_pointer;
926
+ while let Value :: Projection ( pointer, ProjectionElem :: Deref ) =
927
+ * self . get ( copy_from_value)
928
+ {
929
+ copy_from_value = pointer;
930
+ }
931
+ if let Some ( local) = self . try_as_local ( copy_from_value, location) {
932
+ let from_ty = self . local_decls [ local] . ty ;
933
+ if rvalue_ty == from_ty {
934
+ Some ( ( first_pointer, local, false ) )
935
+ } else if Some ( rvalue_ty) == from_ty. builtin_deref ( false ) {
936
+ Some ( ( first_pointer, local, true ) )
937
+ } else {
938
+ None
939
+ }
940
+ } else {
941
+ None
942
+ }
943
+ } else {
944
+ None
945
+ } ;
946
+ if let Some ( ( first_pointer, local, need_deref) ) = copy_from {
947
+ // All fields must correspond one-to-one and come from the same aggregate value.
948
+ if std:: iter:: zip ( field_ops. iter_enumerated ( ) , fields. iter ( ) ) . all (
949
+ |( ( index, _) , & v) | {
950
+ if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) =
951
+ * self . get ( v)
952
+ && first_pointer == pointer
953
+ && from_index == index
954
+ {
955
+ return true ;
956
+ }
957
+ false
958
+ } ,
959
+ ) {
960
+ * rvalue = Rvalue :: Use ( Operand :: Copy ( Place {
961
+ local,
962
+ projection : tcx. mk_place_elems ( if need_deref {
963
+ & [ ProjectionElem :: Deref ]
964
+ } else {
965
+ & [ ]
966
+ } ) ,
967
+ } ) ) ;
968
+ return Some ( first_pointer) ;
969
+ }
970
+ }
971
+ }
972
+
919
973
if let AggregateTy :: RawPtr { data_pointer_ty, output_pointer_ty } = & mut ty {
920
974
let mut was_updated = false ;
921
975
0 commit comments