@@ -876,14 +876,38 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
876
876
None
877
877
}
878
878
879
+ fn try_as_place_elem (
880
+ & mut self ,
881
+ proj : ProjectionElem < VnIndex , Ty < ' tcx > > ,
882
+ loc : Location ,
883
+ ) -> Option < PlaceElem < ' tcx > > {
884
+ Some ( match proj {
885
+ ProjectionElem :: Deref => ProjectionElem :: Deref ,
886
+ ProjectionElem :: Field ( idx, ty) => ProjectionElem :: Field ( idx, ty) ,
887
+ ProjectionElem :: Index ( idx) => {
888
+ return self . try_as_local ( idx, loc) . map ( |l| ProjectionElem :: Index ( l) ) ;
889
+ }
890
+ ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
891
+ ProjectionElem :: ConstantIndex { offset, min_length, from_end }
892
+ }
893
+ ProjectionElem :: Subslice { from, to, from_end } => {
894
+ ProjectionElem :: Subslice { from, to, from_end }
895
+ }
896
+ ProjectionElem :: Downcast ( symbol, idx) => ProjectionElem :: Downcast ( symbol, idx) ,
897
+ ProjectionElem :: OpaqueCast ( idx) => ProjectionElem :: OpaqueCast ( idx) ,
898
+ ProjectionElem :: Subtype ( idx) => ProjectionElem :: Subtype ( idx) ,
899
+ } )
900
+ }
901
+
879
902
fn simplify_aggregate (
880
903
& mut self ,
881
904
rvalue : & mut Rvalue < ' tcx > ,
882
905
location : Location ,
883
906
) -> Option < VnIndex > {
907
+ let tcx = self . tcx ;
908
+ let rvalue_ty = rvalue. ty ( self . local_decls , tcx) ;
884
909
let Rvalue :: Aggregate ( box ref kind, ref mut field_ops) = * rvalue else { bug ! ( ) } ;
885
910
886
- let tcx = self . tcx ;
887
911
if field_ops. is_empty ( ) {
888
912
let is_zst = match * kind {
889
913
AggregateKind :: Array ( ..)
@@ -898,8 +922,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
898
922
} ;
899
923
900
924
if is_zst {
901
- let ty = rvalue. ty ( self . local_decls , tcx) ;
902
- return self . insert_constant ( Const :: zero_sized ( ty) ) ;
925
+ return self . insert_constant ( Const :: zero_sized ( rvalue_ty) ) ;
903
926
}
904
927
}
905
928
@@ -934,6 +957,58 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
934
957
. collect ( ) ;
935
958
let mut fields = fields?;
936
959
960
+ if let AggregateTy :: Def ( _, _) = & mut ty
961
+ && !fields. is_empty ( )
962
+ {
963
+ // All fields must correspond one-to-one and come from the same aggregate value.
964
+ if let Value :: Projection ( copy_from_value, _) = * self . get ( fields[ 0 ] )
965
+ && fields. iter ( ) . enumerate ( ) . all ( |( index, & v) | {
966
+ if let Value :: Projection ( pointer, ProjectionElem :: Field ( from_index, _) ) =
967
+ * self . get ( v)
968
+ && copy_from_value == pointer
969
+ && from_index. index ( ) == index
970
+ {
971
+ return true ;
972
+ }
973
+ false
974
+ } )
975
+ {
976
+ let mut projection = SmallVec :: < [ PlaceElem < ' tcx > ; 1 ] > :: new ( ) ;
977
+ let mut copy_from_local_value = copy_from_value;
978
+ loop {
979
+ if let Some ( local) = self . try_as_local ( copy_from_local_value, location) {
980
+ projection. reverse ( ) ;
981
+ if let Some ( ProjectionElem :: Downcast ( _, _) ) = projection. last ( ) {
982
+ projection. pop ( ) ;
983
+ }
984
+ let place =
985
+ Place { local, projection : tcx. mk_place_elems ( projection. as_slice ( ) ) } ;
986
+ if rvalue_ty == place. ty ( self . local_decls , tcx) . ty {
987
+ self . reused_locals . insert ( local) ;
988
+ * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
989
+ return Some ( copy_from_value) ;
990
+ }
991
+ break ;
992
+ } else if let Value :: Projection ( pointer, proj) =
993
+ * self . get ( copy_from_local_value)
994
+ && let Some ( proj) = self . try_as_place_elem ( proj, location)
995
+ {
996
+ // The copied variant must be identical.
997
+ if let ProjectionElem :: Downcast ( _, read_variant) = proj
998
+ && projection. is_empty ( )
999
+ && variant_index != read_variant
1000
+ {
1001
+ break ;
1002
+ }
1003
+ projection. push ( proj) ;
1004
+ copy_from_local_value = pointer;
1005
+ } else {
1006
+ break ;
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+
937
1012
if let AggregateTy :: RawPtr { data_pointer_ty, output_pointer_ty } = & mut ty {
938
1013
let mut was_updated = false ;
939
1014
0 commit comments