@@ -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
} ;
@@ -698,6 +723,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
698
723
// Invariant: `value` holds the value up-to the `index`th projection excluded.
699
724
let mut value = self . locals [ place. local ] ?;
700
725
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
+ }
701
734
if let Some ( local) = self . try_as_local ( value, location) {
702
735
// Both `local` and `Place { local: place.local, projection: projection[..index] }`
703
736
// hold the same value. Therefore, following place holds the value in the original
@@ -709,6 +742,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
709
742
value = self . project ( base, value, proj) ?;
710
743
}
711
744
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
+ }
712
753
if let Some ( new_local) = self . try_as_local ( value, location) {
713
754
place_ref = PlaceRef { local : new_local, projection : & [ ] } ;
714
755
}
@@ -777,18 +818,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
777
818
778
819
// Operations.
779
820
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) ;
792
823
}
793
824
Rvalue :: BinaryOp ( op, box ( ref mut lhs, ref mut rhs) ) => {
794
825
let ty = lhs. ty ( self . local_decls , self . tcx ) ;
@@ -876,6 +907,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
876
907
}
877
908
}
878
909
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
+
879
916
let ( ty, variant_index) = match * kind {
880
917
AggregateKind :: Array ( ..) => {
881
918
assert ! ( !fields. is_empty( ) ) ;
@@ -895,12 +932,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
895
932
AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
896
933
} ;
897
934
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
935
if let AggregateTy :: Array = ty
905
936
&& fields. len ( ) > 4
906
937
{
@@ -1031,6 +1062,50 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1031
1062
}
1032
1063
}
1033
1064
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
+
1034
1109
fn simplify_len ( & mut self , place : & mut Place < ' tcx > , location : Location ) -> Option < VnIndex > {
1035
1110
// Trivial case: we are fetching a statically known length.
1036
1111
let place_ty = place. ty ( self . local_decls , self . tcx ) . ty ;
@@ -1178,6 +1253,51 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
1178
1253
self . tcx
1179
1254
}
1180
1255
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
+
1181
1301
fn visit_place ( & mut self , place : & mut Place < ' tcx > , _: PlaceContext , location : Location ) {
1182
1302
self . simplify_place_projection ( place, location) ;
1183
1303
}
0 commit comments