@@ -93,7 +93,6 @@ use rustc_index::IndexVec;
9393use rustc_middle:: mir:: interpret:: GlobalAlloc ;
9494use rustc_middle:: mir:: visit:: * ;
9595use rustc_middle:: mir:: * ;
96- use rustc_middle:: ty:: adjustment:: PointerCoercion ;
9796use rustc_middle:: ty:: layout:: LayoutOf ;
9897use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeAndMut } ;
9998use rustc_span:: def_id:: DefId ;
@@ -154,6 +153,9 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
154153 state. next_opaque = None ;
155154
156155 let reverse_postorder = body. basic_blocks . reverse_postorder ( ) . to_vec ( ) ;
156+ for dbg in body. var_debug_info . iter_mut ( ) {
157+ state. visit_var_debug_info ( dbg) ;
158+ }
157159 for bb in reverse_postorder {
158160 let data = & mut body. basic_blocks . as_mut_preserves_cfg ( ) [ bb] ;
159161 state. visit_basic_block_data ( bb, data) ;
@@ -551,6 +553,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
551553 }
552554 value. offset ( Size :: ZERO , to, & self . ecx ) . ok ( ) ?
553555 }
556+ CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize ) => {
557+ let src = self . evaluated [ value] . as_ref ( ) ?;
558+ let to = self . ecx . layout_of ( to) . ok ( ) ?;
559+ let dest = self . ecx . allocate ( to, MemoryKind :: Stack ) . ok ( ) ?;
560+ self . ecx . unsize_into ( src, to, & dest. clone ( ) . into ( ) ) . ok ( ) ?;
561+ self . ecx
562+ . alloc_mark_immutable ( dest. ptr ( ) . provenance . unwrap ( ) . alloc_id ( ) )
563+ . ok ( ) ?;
564+ dest. into ( )
565+ }
566+ CastKind :: FnPtrToPtr
567+ | CastKind :: PtrToPtr
568+ | CastKind :: PointerCoercion (
569+ ty:: adjustment:: PointerCoercion :: MutToConstPointer
570+ | ty:: adjustment:: PointerCoercion :: ArrayToPointer
571+ | ty:: adjustment:: PointerCoercion :: UnsafeFnPointer ,
572+ ) => {
573+ let src = self . evaluated [ value] . as_ref ( ) ?;
574+ let src = self . ecx . read_immediate ( src) . ok ( ) ?;
575+ let to = self . ecx . layout_of ( to) . ok ( ) ?;
576+ let ret = self . ecx . ptr_to_ptr ( & src, to) . ok ( ) ?;
577+ ret. into ( )
578+ }
554579 _ => return None ,
555580 } ,
556581 } ;
@@ -698,6 +723,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
698723 // Invariant: `value` holds the value up-to the `index`th projection excluded.
699724 let mut value = self . locals [ place. local ] ?;
700725 for ( index, proj) in place. projection . iter ( ) . enumerate ( ) {
726+ if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = * self . get ( value)
727+ && let Value :: Address { place : mut pointee, kind, .. } = * self . get ( pointer)
728+ && let AddressKind :: Ref ( BorrowKind :: Shared ) = kind
729+ && let Some ( v) = self . simplify_place_value ( & mut pointee, location)
730+ {
731+ value = v;
732+ place_ref = pointee. project_deeper ( & place. projection [ index..] , self . tcx ) . as_ref ( ) ;
733+ }
701734 if let Some ( local) = self . try_as_local ( value, location) {
702735 // Both `local` and `Place { local: place.local, projection: projection[..index] }`
703736 // hold the same value. Therefore, following place holds the value in the original
@@ -709,6 +742,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
709742 value = self . project ( base, value, proj) ?;
710743 }
711744
745+ if let Value :: Projection ( pointer, ProjectionElem :: Deref ) = * self . get ( value)
746+ && let Value :: Address { place : mut pointee, kind, .. } = * self . get ( pointer)
747+ && let AddressKind :: Ref ( BorrowKind :: Shared ) = kind
748+ && let Some ( v) = self . simplify_place_value ( & mut pointee, location)
749+ {
750+ value = v;
751+ place_ref = pointee. project_deeper ( & [ ] , self . tcx ) . as_ref ( ) ;
752+ }
712753 if let Some ( new_local) = self . try_as_local ( value, location) {
713754 place_ref = PlaceRef { local : new_local, projection : & [ ] } ;
714755 }
@@ -777,18 +818,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
777818
778819 // Operations.
779820 Rvalue :: Len ( ref mut place) => return self . simplify_len ( place, location) ,
780- Rvalue :: Cast ( kind, ref mut value, to) => {
781- let from = value. ty ( self . local_decls , self . tcx ) ;
782- let value = self . simplify_operand ( value, location) ?;
783- if let CastKind :: PointerCoercion (
784- PointerCoercion :: ReifyFnPointer | PointerCoercion :: ClosureFnPointer ( _) ,
785- ) = kind
786- {
787- // Each reification of a generic fn may get a different pointer.
788- // Do not try to merge them.
789- return self . new_opaque ( ) ;
790- }
791- Value :: Cast { kind, value, from, to }
821+ Rvalue :: Cast ( ref mut kind, ref mut value, to) => {
822+ return self . simplify_cast ( kind, value, to, location) ;
792823 }
793824 Rvalue :: BinaryOp ( op, box ( ref mut lhs, ref mut rhs) ) => {
794825 let ty = lhs. ty ( self . local_decls , self . tcx ) ;
@@ -876,6 +907,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
876907 }
877908 }
878909
910+ let fields: Option < Vec < _ > > = fields
911+ . iter_mut ( )
912+ . map ( |op| self . simplify_operand ( op, location) . or_else ( || self . new_opaque ( ) ) )
913+ . collect ( ) ;
914+ let fields = fields?;
915+
879916 let ( ty, variant_index) = match * kind {
880917 AggregateKind :: Array ( ..) => {
881918 assert ! ( !fields. is_empty( ) ) ;
@@ -895,12 +932,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
895932 AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
896933 } ;
897934
898- let fields: Option < Vec < _ > > = fields
899- . iter_mut ( )
900- . map ( |op| self . simplify_operand ( op, location) . or_else ( || self . new_opaque ( ) ) )
901- . collect ( ) ;
902- let fields = fields?;
903-
904935 if let AggregateTy :: Array = ty
905936 && fields. len ( ) > 4
906937 {
@@ -1031,6 +1062,50 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10311062 }
10321063 }
10331064
1065+ fn simplify_cast (
1066+ & mut self ,
1067+ kind : & mut CastKind ,
1068+ operand : & mut Operand < ' tcx > ,
1069+ to : Ty < ' tcx > ,
1070+ location : Location ,
1071+ ) -> Option < VnIndex > {
1072+ use rustc_middle:: ty:: adjustment:: PointerCoercion :: * ;
1073+ use CastKind :: * ;
1074+
1075+ let mut from = operand. ty ( self . local_decls , self . tcx ) ;
1076+ let mut value = self . simplify_operand ( operand, location) ?;
1077+ if from == to {
1078+ return Some ( value) ;
1079+ }
1080+
1081+ if let CastKind :: PointerCoercion ( ReifyFnPointer | ClosureFnPointer ( _) ) = kind {
1082+ // Each reification of a generic fn may get a different pointer.
1083+ // Do not try to merge them.
1084+ return self . new_opaque ( ) ;
1085+ }
1086+
1087+ if let PtrToPtr | PointerCoercion ( MutToConstPointer ) = kind
1088+ && let Value :: Cast { kind : inner_kind, value : inner_value, from : inner_from, to : _ } =
1089+ * self . get ( value)
1090+ && let PtrToPtr | PointerCoercion ( MutToConstPointer ) = inner_kind
1091+ {
1092+ from = inner_from;
1093+ value = inner_value;
1094+ * kind = PtrToPtr ;
1095+ if inner_from == to {
1096+ return Some ( inner_value) ;
1097+ }
1098+ if let Some ( const_) = self . try_as_constant ( value) {
1099+ * operand = Operand :: Constant ( Box :: new ( const_) ) ;
1100+ } else if let Some ( local) = self . try_as_local ( value, location) {
1101+ * operand = Operand :: Copy ( local. into ( ) ) ;
1102+ self . reused_locals . insert ( local) ;
1103+ }
1104+ }
1105+
1106+ Some ( self . insert ( Value :: Cast { kind : * kind, value, from, to } ) )
1107+ }
1108+
10341109 fn simplify_len ( & mut self , place : & mut Place < ' tcx > , location : Location ) -> Option < VnIndex > {
10351110 // Trivial case: we are fetching a statically known length.
10361111 let place_ty = place. ty ( self . local_decls , self . tcx ) . ty ;
@@ -1178,6 +1253,51 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
11781253 self . tcx
11791254 }
11801255
1256+ fn visit_var_debug_info ( & mut self , var_debug_info : & mut VarDebugInfo < ' tcx > ) {
1257+ let mut replace_dereffed = |place : & mut Place < ' tcx > | -> Option < !> {
1258+ let last_deref = place. projection . iter ( ) . rposition ( |e| e == PlaceElem :: Deref ) ?;
1259+
1260+ // Another place that holds the same value.
1261+ let mut place_ref = place. as_ref ( ) ;
1262+ let mut value = self . locals [ place. local ] ?;
1263+
1264+ for ( index, & proj) in place. projection [ ..last_deref] . iter ( ) . enumerate ( ) {
1265+ if let Some ( candidates) = self . rev_locals . get ( value)
1266+ && let Some ( & local) = candidates. first ( )
1267+ {
1268+ place_ref = PlaceRef { local, projection : & place. projection [ index..] } ;
1269+ }
1270+
1271+ let place_upto =
1272+ PlaceRef { local : place. local , projection : & place. projection [ ..index] } ;
1273+ if let Some ( projected) = self . project ( place_upto, value, proj) {
1274+ value = projected;
1275+ } else {
1276+ if place_ref. projection . len ( ) < place. projection . len ( ) {
1277+ * place = place_ref. project_deeper ( & [ ] , self . tcx ) ;
1278+ }
1279+ return None ;
1280+ }
1281+ }
1282+
1283+ if let Some ( candidates) = self . rev_locals . get ( value)
1284+ && let Some ( & local) = candidates. first ( )
1285+ {
1286+ let place_ref = PlaceRef { local, projection : & place. projection [ last_deref..] } ;
1287+ * place = place_ref. project_deeper ( & [ ] , self . tcx ) ;
1288+ }
1289+
1290+ return None ;
1291+ } ;
1292+
1293+ match & mut var_debug_info. value {
1294+ VarDebugInfoContents :: Const ( _) => { }
1295+ VarDebugInfoContents :: Place ( place) => {
1296+ replace_dereffed ( place) ;
1297+ }
1298+ }
1299+ }
1300+
11811301 fn visit_place ( & mut self , place : & mut Place < ' tcx > , _: PlaceContext , location : Location ) {
11821302 self . simplify_place_projection ( place, location) ;
11831303 }
0 commit comments