@@ -875,6 +875,95 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
875875        None 
876876    } 
877877
878+     fn  try_as_place_elem ( 
879+         & mut  self , 
880+         proj :  ProjectionElem < VnIndex ,  Ty < ' tcx > > , 
881+         loc :  Location , 
882+     )  -> Option < PlaceElem < ' tcx > >  { 
883+         Some ( match  proj { 
884+             ProjectionElem :: Deref  => ProjectionElem :: Deref , 
885+             ProjectionElem :: Field ( idx,  ty)  => ProjectionElem :: Field ( idx,  ty) , 
886+             ProjectionElem :: Index ( idx)  => { 
887+                 let  Some ( local)  = self . try_as_local ( idx,  loc)  else  { 
888+                     return  None ; 
889+                 } ; 
890+                 self . reused_locals . insert ( local) ; 
891+                 ProjectionElem :: Index ( local) 
892+             } 
893+             ProjectionElem :: ConstantIndex  {  offset,  min_length,  from_end }  => { 
894+                 ProjectionElem :: ConstantIndex  {  offset,  min_length,  from_end } 
895+             } 
896+             ProjectionElem :: Subslice  {  from,  to,  from_end }  => { 
897+                 ProjectionElem :: Subslice  {  from,  to,  from_end } 
898+             } 
899+             ProjectionElem :: Downcast ( symbol,  idx)  => ProjectionElem :: Downcast ( symbol,  idx) , 
900+             ProjectionElem :: OpaqueCast ( idx)  => ProjectionElem :: OpaqueCast ( idx) , 
901+             ProjectionElem :: Subtype ( idx)  => ProjectionElem :: Subtype ( idx) , 
902+         } ) 
903+     } 
904+ 
905+     fn  simplify_aggregate_to_copy ( 
906+         & mut  self , 
907+         rvalue :  & mut  Rvalue < ' tcx > , 
908+         location :  Location , 
909+         fields :  & [ VnIndex ] , 
910+         variant_index :  VariantIdx , 
911+     )  -> Option < VnIndex >  { 
912+         let  Some ( & first_field)  = fields. first ( )  else  { 
913+             return  None ; 
914+         } ; 
915+         let  Value :: Projection ( copy_from_value,  _)  = * self . get ( first_field)  else  { 
916+             return  None ; 
917+         } ; 
918+         // All fields must correspond one-to-one and come from the same aggregate value. 
919+         if  fields. iter ( ) . enumerate ( ) . any ( |( index,  & v) | { 
920+             if  let  Value :: Projection ( pointer,  ProjectionElem :: Field ( from_index,  _) )  = * self . get ( v) 
921+                 && copy_from_value == pointer
922+                 && from_index. index ( )  == index
923+             { 
924+                 return  false ; 
925+             } 
926+             true 
927+         } )  { 
928+             return  None ; 
929+         } 
930+ 
931+         let  mut  copy_from_local_value = copy_from_value; 
932+         if  let  Value :: Projection ( pointer,  proj)  = * self . get ( copy_from_value) 
933+             && let  ProjectionElem :: Downcast ( _,  read_variant)  = proj
934+         { 
935+             if  variant_index == read_variant { 
936+                 // When copying a variant, there is no need to downcast. 
937+                 copy_from_local_value = pointer; 
938+             }  else  { 
939+                 // The copied variant must be identical. 
940+                 return  None ; 
941+             } 
942+         } 
943+ 
944+         let  tcx = self . tcx ; 
945+         let  mut  projection = SmallVec :: < [ PlaceElem < ' tcx > ;  1 ] > :: new ( ) ; 
946+         loop  { 
947+             if  let  Some ( local)  = self . try_as_local ( copy_from_local_value,  location)  { 
948+                 projection. reverse ( ) ; 
949+                 let  place = Place  {  local,  projection :  tcx. mk_place_elems ( projection. as_slice ( ) )  } ; 
950+                 if  rvalue. ty ( self . local_decls ,  tcx)  == place. ty ( self . local_decls ,  tcx) . ty  { 
951+                     self . reused_locals . insert ( local) ; 
952+                     * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ; 
953+                     return  Some ( copy_from_value) ; 
954+                 } 
955+                 return  None ; 
956+             }  else  if  let  Value :: Projection ( pointer,  proj)  = * self . get ( copy_from_local_value) 
957+                 && let  Some ( proj)  = self . try_as_place_elem ( proj,  location) 
958+             { 
959+                 projection. push ( proj) ; 
960+                 copy_from_local_value = pointer; 
961+             }  else  { 
962+                 return  None ; 
963+             } 
964+         } 
965+     } 
966+ 
878967    fn  simplify_aggregate ( 
879968        & mut  self , 
880969        rvalue :  & mut  Rvalue < ' tcx > , 
@@ -971,6 +1060,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
9711060            } 
9721061        } 
9731062
1063+         if  let  AggregateTy :: Def ( _,  _)  = ty
1064+             && let  Some ( value)  =
1065+                 self . simplify_aggregate_to_copy ( rvalue,  location,  & fields,  variant_index) 
1066+         { 
1067+             return  Some ( value) ; 
1068+         } 
1069+ 
9741070        Some ( self . insert ( Value :: Aggregate ( ty,  variant_index,  fields) ) ) 
9751071    } 
9761072
@@ -1485,7 +1581,7 @@ impl<'tcx> VnState<'_, 'tcx> {
14851581    } 
14861582
14871583    /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`, 
1488-      /// return it. 
1584+      /// return it. If you used this local, add it to `reused_locals` to remove storage statements.  
14891585     fn  try_as_local ( & mut  self ,  index :  VnIndex ,  loc :  Location )  -> Option < Local >  { 
14901586        let  other = self . rev_locals . get ( index) ?; 
14911587        other
0 commit comments