@@ -93,7 +93,6 @@ use rustc_index::IndexVec;
93
93
use rustc_middle:: mir:: interpret:: GlobalAlloc ;
94
94
use rustc_middle:: mir:: visit:: * ;
95
95
use rustc_middle:: mir:: * ;
96
- use rustc_middle:: ty:: adjustment:: PointerCoercion ;
97
96
use rustc_middle:: ty:: layout:: LayoutOf ;
98
97
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeAndMut } ;
99
98
use rustc_span:: def_id:: DefId ;
@@ -154,6 +153,9 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
154
153
state. next_opaque = None ;
155
154
156
155
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
+ }
157
159
for bb in reverse_postorder {
158
160
let data = & mut body. basic_blocks . as_mut_preserves_cfg ( ) [ bb] ;
159
161
state. visit_basic_block_data ( bb, data) ;
@@ -551,6 +553,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
551
553
}
552
554
value. offset ( Size :: ZERO , to, & self . ecx ) . ok ( ) ?
553
555
}
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
+ }
554
579
_ => return None ,
555
580
} ,
556
581
} ;
@@ -777,18 +802,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
777
802
778
803
// Operations.
779
804
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) ;
792
807
}
793
808
Rvalue :: BinaryOp ( op, box ( ref mut lhs, ref mut rhs) ) => {
794
809
let ty = lhs. ty ( self . local_decls , self . tcx ) ;
@@ -876,6 +891,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
876
891
}
877
892
}
878
893
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
+
879
900
let ( ty, variant_index) = match * kind {
880
901
AggregateKind :: Array ( ..) => {
881
902
assert ! ( !fields. is_empty( ) ) ;
@@ -895,12 +916,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
895
916
AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
896
917
} ;
897
918
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
-
904
919
if let AggregateTy :: Array = ty
905
920
&& fields. len ( ) > 4
906
921
{
@@ -1031,6 +1046,50 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1031
1046
}
1032
1047
}
1033
1048
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
+
1034
1093
fn simplify_len ( & mut self , place : & mut Place < ' tcx > , location : Location ) -> Option < VnIndex > {
1035
1094
// Trivial case: we are fetching a statically known length.
1036
1095
let place_ty = place. ty ( self . local_decls , self . tcx ) . ty ;
@@ -1178,6 +1237,51 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1178
1237
self . tcx
1179
1238
}
1180
1239
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
+
1181
1285
fn visit_place ( & mut self , place : & mut Place < ' tcx > , _: PlaceContext , location : Location ) {
1182
1286
self . simplify_place_projection ( place, location) ;
1183
1287
}
0 commit comments