@@ -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 } ;
@@ -777,18 +802,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
777802
778803 // Operations.
779804 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 }
805+ Rvalue :: Cast ( ref mut kind, ref mut value, to) => {
806+ return self . simplify_cast ( kind, value, to, location) ;
792807 }
793808 Rvalue :: BinaryOp ( op, box ( ref mut lhs, ref mut rhs) ) => {
794809 let ty = lhs. ty ( self . local_decls , self . tcx ) ;
@@ -876,6 +891,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
876891 }
877892 }
878893
894+ let fields: Option < Vec < _ > > = fields
895+ . iter_mut ( )
896+ . map ( |op| self . simplify_operand ( op, location) . or_else ( || self . new_opaque ( ) ) )
897+ . collect ( ) ;
898+ let fields = fields?;
899+
879900 let ( ty, variant_index) = match * kind {
880901 AggregateKind :: Array ( ..) => {
881902 assert ! ( !fields. is_empty( ) ) ;
@@ -895,12 +916,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
895916 AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
896917 } ;
897918
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-
904919 if let AggregateTy :: Array = ty
905920 && fields. len ( ) > 4
906921 {
@@ -1031,6 +1046,50 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10311046 }
10321047 }
10331048
1049+ fn simplify_cast (
1050+ & mut self ,
1051+ kind : & mut CastKind ,
1052+ operand : & mut Operand < ' tcx > ,
1053+ to : Ty < ' tcx > ,
1054+ location : Location ,
1055+ ) -> Option < VnIndex > {
1056+ use rustc_middle:: ty:: adjustment:: PointerCoercion :: * ;
1057+ use CastKind :: * ;
1058+
1059+ let mut from = operand. ty ( self . local_decls , self . tcx ) ;
1060+ let mut value = self . simplify_operand ( operand, location) ?;
1061+ if from == to {
1062+ return Some ( value) ;
1063+ }
1064+
1065+ if let CastKind :: PointerCoercion ( ReifyFnPointer | ClosureFnPointer ( _) ) = kind {
1066+ // Each reification of a generic fn may get a different pointer.
1067+ // Do not try to merge them.
1068+ return self . new_opaque ( ) ;
1069+ }
1070+
1071+ if let PtrToPtr | PointerCoercion ( MutToConstPointer ) = kind
1072+ && let Value :: Cast { kind : inner_kind, value : inner_value, from : inner_from, to : _ } =
1073+ * self . get ( value)
1074+ && let PtrToPtr | PointerCoercion ( MutToConstPointer ) = inner_kind
1075+ {
1076+ from = inner_from;
1077+ value = inner_value;
1078+ * kind = PtrToPtr ;
1079+ if inner_from == to {
1080+ return Some ( inner_value) ;
1081+ }
1082+ if let Some ( const_) = self . try_as_constant ( value) {
1083+ * operand = Operand :: Constant ( Box :: new ( const_) ) ;
1084+ } else if let Some ( local) = self . try_as_local ( value, location) {
1085+ * operand = Operand :: Copy ( local. into ( ) ) ;
1086+ self . reused_locals . insert ( local) ;
1087+ }
1088+ }
1089+
1090+ Some ( self . insert ( Value :: Cast { kind : * kind, value, from, to } ) )
1091+ }
1092+
10341093 fn simplify_len ( & mut self , place : & mut Place < ' tcx > , location : Location ) -> Option < VnIndex > {
10351094 // Trivial case: we are fetching a statically known length.
10361095 let place_ty = place. ty ( self . local_decls , self . tcx ) . ty ;
@@ -1178,6 +1237,51 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
11781237 self . tcx
11791238 }
11801239
1240+ fn visit_var_debug_info ( & mut self , var_debug_info : & mut VarDebugInfo < ' tcx > ) {
1241+ let mut replace_dereffed = |place : & mut Place < ' tcx > | -> Option < !> {
1242+ let last_deref = place. projection . iter ( ) . rposition ( |e| e == PlaceElem :: Deref ) ?;
1243+
1244+ // Another place that holds the same value.
1245+ let mut place_ref = place. as_ref ( ) ;
1246+ let mut value = self . locals [ place. local ] ?;
1247+
1248+ for ( index, & proj) in place. projection [ ..last_deref] . iter ( ) . enumerate ( ) {
1249+ if let Some ( candidates) = self . rev_locals . get ( value)
1250+ && let Some ( & local) = candidates. first ( )
1251+ {
1252+ place_ref = PlaceRef { local, projection : & place. projection [ index..] } ;
1253+ }
1254+
1255+ let place_upto =
1256+ PlaceRef { local : place. local , projection : & place. projection [ ..index] } ;
1257+ if let Some ( projected) = self . project ( place_upto, value, proj) {
1258+ value = projected;
1259+ } else {
1260+ if place_ref. projection . len ( ) < place. projection . len ( ) {
1261+ * place = place_ref. project_deeper ( & [ ] , self . tcx ) ;
1262+ }
1263+ return None ;
1264+ }
1265+ }
1266+
1267+ if let Some ( candidates) = self . rev_locals . get ( value)
1268+ && let Some ( & local) = candidates. first ( )
1269+ {
1270+ let place_ref = PlaceRef { local, projection : & place. projection [ last_deref..] } ;
1271+ * place = place_ref. project_deeper ( & [ ] , self . tcx ) ;
1272+ }
1273+
1274+ return None ;
1275+ } ;
1276+
1277+ match & mut var_debug_info. value {
1278+ VarDebugInfoContents :: Const ( _) => { }
1279+ VarDebugInfoContents :: Place ( place) => {
1280+ replace_dereffed ( place) ;
1281+ }
1282+ }
1283+ }
1284+
11811285 fn visit_place ( & mut self , place : & mut Place < ' tcx > , _: PlaceContext , location : Location ) {
11821286 self . simplify_place_projection ( place, location) ;
11831287 }
0 commit comments