@@ -823,18 +823,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
823823 return self . simplify_cast ( kind, value, to, location) ;
824824 }
825825 Rvalue :: BinaryOp ( op, box ( ref mut lhs, ref mut rhs) ) => {
826- let ty = lhs. ty ( self . local_decls , self . tcx ) ;
827- let lhs = self . simplify_operand ( lhs, location) ;
828- let rhs = self . simplify_operand ( rhs, location) ;
829- // Only short-circuit options after we called `simplify_operand`
830- // on both operands for side effect.
831- let lhs = lhs?;
832- let rhs = rhs?;
833-
834- if let Some ( value) = self . simplify_binary ( op, ty, lhs, rhs) {
835- return Some ( value) ;
836- }
837- Value :: BinaryOp ( op, lhs, rhs)
826+ return self . simplify_binary ( op, lhs, rhs, location) ;
838827 }
839828 Rvalue :: UnaryOp ( op, ref mut arg_op) => {
840829 return self . simplify_unary ( op, arg_op, location) ;
@@ -987,23 +976,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
987976 // `*const [T]` -> `*const T` which remove metadata.
988977 // We run on potentially-generic MIR, though, so unlike codegen
989978 // we can't always know exactly what the metadata are.
990- // Thankfully, equality on `ptr_metadata_ty_or_tail` gives us
991- // what we need: `Ok(meta_ty)` if the metadata is known, or
992- // `Err(tail_ty)` if not. Matching metadata is ok, but if
993- // that's not known, then matching tail types is also ok,
994- // allowing things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`.
995- // FIXME: Would it be worth trying to normalize, rather than
996- // passing the identity closure? Or are the types in the
997- // Cast realistically about as normalized as we can get anyway?
979+ // To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`,
980+ // it's fine to get a projection as the type.
998981 Value :: Cast { kind : CastKind :: PtrToPtr , value : inner, from, to }
999- if from
1000- . builtin_deref ( true )
1001- . unwrap ( )
1002- . ptr_metadata_ty_or_tail ( self . tcx , |t| t)
1003- == to
1004- . builtin_deref ( true )
1005- . unwrap ( )
1006- . ptr_metadata_ty_or_tail ( self . tcx , |t| t) =>
982+ if self . pointers_have_same_metadata ( * from, * to) =>
1007983 {
1008984 arg_index = * inner;
1009985 was_updated = true ;
@@ -1068,6 +1044,52 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10681044
10691045 #[ instrument( level = "trace" , skip( self ) , ret) ]
10701046 fn simplify_binary (
1047+ & mut self ,
1048+ op : BinOp ,
1049+ lhs_operand : & mut Operand < ' tcx > ,
1050+ rhs_operand : & mut Operand < ' tcx > ,
1051+ location : Location ,
1052+ ) -> Option < VnIndex > {
1053+ let lhs = self . simplify_operand ( lhs_operand, location) ;
1054+ let rhs = self . simplify_operand ( rhs_operand, location) ;
1055+ // Only short-circuit options after we called `simplify_operand`
1056+ // on both operands for side effect.
1057+ let mut lhs = lhs?;
1058+ let mut rhs = rhs?;
1059+
1060+ let lhs_ty = lhs_operand. ty ( self . local_decls , self . tcx ) ;
1061+
1062+ // If we're comparing pointers, remove `PtrToPtr` casts if the from
1063+ // types of both casts and the metadata all match.
1064+ if let BinOp :: Eq | BinOp :: Ne | BinOp :: Lt | BinOp :: Le | BinOp :: Gt | BinOp :: Ge = op
1065+ && lhs_ty. is_any_ptr ( )
1066+ && let Value :: Cast {
1067+ kind : CastKind :: PtrToPtr , value : lhs_value, from : lhs_from, ..
1068+ } = self . get ( lhs)
1069+ && let Value :: Cast {
1070+ kind : CastKind :: PtrToPtr , value : rhs_value, from : rhs_from, ..
1071+ } = self . get ( rhs)
1072+ && lhs_from == rhs_from
1073+ && self . pointers_have_same_metadata ( * lhs_from, lhs_ty)
1074+ {
1075+ lhs = * lhs_value;
1076+ rhs = * rhs_value;
1077+ if let Some ( op) = self . try_as_operand ( lhs, location) {
1078+ * lhs_operand = op;
1079+ }
1080+ if let Some ( op) = self . try_as_operand ( rhs, location) {
1081+ * rhs_operand = op;
1082+ }
1083+ }
1084+
1085+ if let Some ( value) = self . simplify_binary_inner ( op, lhs_ty, lhs, rhs) {
1086+ return Some ( value) ;
1087+ }
1088+ let value = Value :: BinaryOp ( op, lhs, rhs) ;
1089+ Some ( self . insert ( value) )
1090+ }
1091+
1092+ fn simplify_binary_inner (
10711093 & mut self ,
10721094 op : BinOp ,
10731095 lhs_ty : Ty < ' tcx > ,
@@ -1228,14 +1250,33 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12281250 }
12291251 }
12301252
1253+ // PtrToPtr-then-PtrToPtr can skip the intermediate step
12311254 if let PtrToPtr = kind
12321255 && let Value :: Cast { kind : inner_kind, value : inner_value, from : inner_from, to : _ } =
12331256 * self . get ( value)
12341257 && let PtrToPtr = inner_kind
12351258 {
12361259 from = inner_from;
12371260 value = inner_value;
1238- * kind = PtrToPtr ;
1261+ was_updated = true ;
1262+ if inner_from == to {
1263+ return Some ( inner_value) ;
1264+ }
1265+ }
1266+
1267+ // PtrToPtr-then-Transmute can just transmute the original, so long as the
1268+ // PtrToPtr didn't change metadata (and thus the size of the pointer)
1269+ if let Transmute = kind
1270+ && let Value :: Cast {
1271+ kind : PtrToPtr ,
1272+ value : inner_value,
1273+ from : inner_from,
1274+ to : inner_to,
1275+ } = * self . get ( value)
1276+ && self . pointers_have_same_metadata ( inner_from, inner_to)
1277+ {
1278+ from = inner_from;
1279+ value = inner_value;
12391280 was_updated = true ;
12401281 if inner_from == to {
12411282 return Some ( inner_value) ;
@@ -1289,6 +1330,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12891330 // Fallback: a symbolic `Len`.
12901331 Some ( self . insert ( Value :: Len ( inner) ) )
12911332 }
1333+
1334+ fn pointers_have_same_metadata ( & self , left_ptr_ty : Ty < ' tcx > , right_ptr_ty : Ty < ' tcx > ) -> bool {
1335+ let left_meta_ty = left_ptr_ty. pointee_metadata_ty_or_projection ( self . tcx ) ;
1336+ let right_meta_ty = right_ptr_ty. pointee_metadata_ty_or_projection ( self . tcx ) ;
1337+ if left_meta_ty == right_meta_ty {
1338+ true
1339+ } else if let Ok ( left) =
1340+ self . tcx . try_normalize_erasing_regions ( self . param_env , left_meta_ty)
1341+ && let Ok ( right) = self . tcx . try_normalize_erasing_regions ( self . param_env , right_meta_ty)
1342+ {
1343+ left == right
1344+ } else {
1345+ false
1346+ }
1347+ }
12921348}
12931349
12941350fn op_to_prop_const < ' tcx > (
0 commit comments