Skip to content

Commit dd1e19e

Browse files
committed
GVN away PtrToPtr before comparisons
Notably this happens in `NonNull::eq` :/
1 parent a76e1d9 commit dd1e19e

6 files changed

+382
-64
lines changed

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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);
@@ -1059,6 +1048,52 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10591048

10601049
#[instrument(level = "trace", skip(self), ret)]
10611050
fn simplify_binary(
1051+
&mut self,
1052+
op: BinOp,
1053+
lhs_operand: &mut Operand<'tcx>,
1054+
rhs_operand: &mut Operand<'tcx>,
1055+
location: Location,
1056+
) -> Option<VnIndex> {
1057+
1058+
let lhs = self.simplify_operand(lhs_operand, location);
1059+
let rhs = self.simplify_operand(rhs_operand, location);
1060+
// Only short-circuit options after we called `simplify_operand`
1061+
// on both operands for side effect.
1062+
let mut lhs = lhs?;
1063+
let mut rhs = rhs?;
1064+
1065+
let lhs_ty = lhs_operand.ty(self.local_decls, self.tcx);
1066+
1067+
// If we're comparing pointers, remove `PtrToPtr` casts if the from
1068+
// types of both casts and the metadata all match.
1069+
if let BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge = op
1070+
&& lhs_ty.is_any_ptr()
1071+
&& let Value::Cast { kind: CastKind::PtrToPtr, value: lhs_value, from: lhs_from, .. } =
1072+
self.get(lhs)
1073+
&& let Value::Cast { kind: CastKind::PtrToPtr, value: rhs_value, from: rhs_from, .. } =
1074+
self.get(rhs)
1075+
&& lhs_from == rhs_from
1076+
&& lhs_from.pointee_metadata_ty_or_projection(self.tcx)
1077+
== lhs_ty.pointee_metadata_ty_or_projection(self.tcx)
1078+
{
1079+
lhs = *lhs_value;
1080+
rhs = *rhs_value;
1081+
if let Some(op) = self.try_as_operand(lhs, location) {
1082+
*lhs_operand = op;
1083+
}
1084+
if let Some(op) = self.try_as_operand(rhs, location) {
1085+
*rhs_operand = op;
1086+
}
1087+
}
1088+
1089+
if let Some(value) = self.simplify_binary_inner(op, lhs_ty, lhs, rhs) {
1090+
return Some(value);
1091+
}
1092+
let value = Value::BinaryOp(op, lhs, rhs);
1093+
Some(self.insert(value))
1094+
}
1095+
1096+
fn simplify_binary_inner(
10621097
&mut self,
10631098
op: BinOp,
10641099
lhs_ty: Ty<'tcx>,
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
- // MIR for `cast_pointer_eq` before GVN
2+
+ // MIR for `cast_pointer_eq` after GVN
3+
4+
fn cast_pointer_eq(_1: *mut u8, _2: *mut u32, _3: *mut u32, _4: *mut [u32]) -> () {
5+
debug p1 => _1;
6+
debug p2 => _2;
7+
debug p3 => _3;
8+
debug p4 => _4;
9+
let mut _0: ();
10+
let _5: *const u32;
11+
let mut _6: *mut u8;
12+
let mut _8: *const u32;
13+
let mut _9: *mut u32;
14+
let mut _11: *const u32;
15+
let mut _12: *mut u32;
16+
let mut _14: *mut [u32];
17+
let mut _16: *const u32;
18+
let mut _17: *const u32;
19+
let mut _19: *const u32;
20+
let mut _20: *const u32;
21+
let mut _22: *const u32;
22+
let mut _23: *const u32;
23+
scope 1 {
24+
debug m1 => _5;
25+
let _7: *const u32;
26+
scope 2 {
27+
debug m2 => _7;
28+
let _10: *const u32;
29+
scope 3 {
30+
debug m3 => _10;
31+
let _13: *const u32;
32+
scope 4 {
33+
debug m4 => _13;
34+
let _15: bool;
35+
scope 5 {
36+
debug eq_different_thing => _15;
37+
let _18: bool;
38+
scope 6 {
39+
debug eq_optimize => _18;
40+
let _21: bool;
41+
scope 7 {
42+
debug eq_thin_fat => _21;
43+
}
44+
}
45+
}
46+
}
47+
}
48+
}
49+
}
50+
51+
bb0: {
52+
- StorageLive(_5);
53+
+ nop;
54+
StorageLive(_6);
55+
_6 = _1;
56+
- _5 = move _6 as *const u32 (PtrToPtr);
57+
+ _5 = _1 as *const u32 (PtrToPtr);
58+
StorageDead(_6);
59+
StorageLive(_7);
60+
- StorageLive(_8);
61+
+ nop;
62+
StorageLive(_9);
63+
_9 = _2;
64+
- _8 = move _9 as *const u32 (PtrToPtr);
65+
+ _8 = _2 as *const u32 (PtrToPtr);
66+
StorageDead(_9);
67+
- _7 = move _8 as *const u32 (PtrToPtr);
68+
- StorageDead(_8);
69+
+ _7 = _8;
70+
+ nop;
71+
StorageLive(_10);
72+
- StorageLive(_11);
73+
+ nop;
74+
StorageLive(_12);
75+
_12 = _3;
76+
- _11 = move _12 as *const u32 (PtrToPtr);
77+
+ _11 = _3 as *const u32 (PtrToPtr);
78+
StorageDead(_12);
79+
- _10 = move _11 as *const u32 (PtrToPtr);
80+
- StorageDead(_11);
81+
- StorageLive(_13);
82+
+ _10 = _11;
83+
+ nop;
84+
+ nop;
85+
StorageLive(_14);
86+
_14 = _4;
87+
- _13 = move _14 as *const u32 (PtrToPtr);
88+
+ _13 = _4 as *const u32 (PtrToPtr);
89+
StorageDead(_14);
90+
StorageLive(_15);
91+
StorageLive(_16);
92+
_16 = _5;
93+
StorageLive(_17);
94+
- _17 = _7;
95+
- _15 = Eq(move _16, move _17);
96+
+ _17 = _8;
97+
+ _15 = Eq(_5, _8);
98+
StorageDead(_17);
99+
StorageDead(_16);
100+
StorageLive(_18);
101+
StorageLive(_19);
102+
- _19 = _7;
103+
+ _19 = _8;
104+
StorageLive(_20);
105+
- _20 = _10;
106+
- _18 = Eq(move _19, move _20);
107+
+ _20 = _11;
108+
+ _18 = Eq(_2, _3);
109+
StorageDead(_20);
110+
StorageDead(_19);
111+
StorageLive(_21);
112+
StorageLive(_22);
113+
- _22 = _10;
114+
+ _22 = _11;
115+
StorageLive(_23);
116+
_23 = _13;
117+
- _21 = Eq(move _22, move _23);
118+
+ _21 = Eq(_11, _13);
119+
StorageDead(_23);
120+
StorageDead(_22);
121+
_0 = const ();
122+
StorageDead(_21);
123+
StorageDead(_18);
124+
StorageDead(_15);
125+
- StorageDead(_13);
126+
+ nop;
127+
StorageDead(_10);
128+
StorageDead(_7);
129+
- StorageDead(_5);
130+
+ nop;
131+
return;
132+
}
133+
}
134+
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
- // MIR for `cast_pointer_eq` before GVN
2+
+ // MIR for `cast_pointer_eq` after GVN
3+
4+
fn cast_pointer_eq(_1: *mut u8, _2: *mut u32, _3: *mut u32, _4: *mut [u32]) -> () {
5+
debug p1 => _1;
6+
debug p2 => _2;
7+
debug p3 => _3;
8+
debug p4 => _4;
9+
let mut _0: ();
10+
let _5: *const u32;
11+
let mut _6: *mut u8;
12+
let mut _8: *const u32;
13+
let mut _9: *mut u32;
14+
let mut _11: *const u32;
15+
let mut _12: *mut u32;
16+
let mut _14: *mut [u32];
17+
let mut _16: *const u32;
18+
let mut _17: *const u32;
19+
let mut _19: *const u32;
20+
let mut _20: *const u32;
21+
let mut _22: *const u32;
22+
let mut _23: *const u32;
23+
scope 1 {
24+
debug m1 => _5;
25+
let _7: *const u32;
26+
scope 2 {
27+
debug m2 => _7;
28+
let _10: *const u32;
29+
scope 3 {
30+
debug m3 => _10;
31+
let _13: *const u32;
32+
scope 4 {
33+
debug m4 => _13;
34+
let _15: bool;
35+
scope 5 {
36+
debug eq_different_thing => _15;
37+
let _18: bool;
38+
scope 6 {
39+
debug eq_optimize => _18;
40+
let _21: bool;
41+
scope 7 {
42+
debug eq_thin_fat => _21;
43+
}
44+
}
45+
}
46+
}
47+
}
48+
}
49+
}
50+
51+
bb0: {
52+
- StorageLive(_5);
53+
+ nop;
54+
StorageLive(_6);
55+
_6 = _1;
56+
- _5 = move _6 as *const u32 (PtrToPtr);
57+
+ _5 = _1 as *const u32 (PtrToPtr);
58+
StorageDead(_6);
59+
StorageLive(_7);
60+
- StorageLive(_8);
61+
+ nop;
62+
StorageLive(_9);
63+
_9 = _2;
64+
- _8 = move _9 as *const u32 (PtrToPtr);
65+
+ _8 = _2 as *const u32 (PtrToPtr);
66+
StorageDead(_9);
67+
- _7 = move _8 as *const u32 (PtrToPtr);
68+
- StorageDead(_8);
69+
+ _7 = _8;
70+
+ nop;
71+
StorageLive(_10);
72+
- StorageLive(_11);
73+
+ nop;
74+
StorageLive(_12);
75+
_12 = _3;
76+
- _11 = move _12 as *const u32 (PtrToPtr);
77+
+ _11 = _3 as *const u32 (PtrToPtr);
78+
StorageDead(_12);
79+
- _10 = move _11 as *const u32 (PtrToPtr);
80+
- StorageDead(_11);
81+
- StorageLive(_13);
82+
+ _10 = _11;
83+
+ nop;
84+
+ nop;
85+
StorageLive(_14);
86+
_14 = _4;
87+
- _13 = move _14 as *const u32 (PtrToPtr);
88+
+ _13 = _4 as *const u32 (PtrToPtr);
89+
StorageDead(_14);
90+
StorageLive(_15);
91+
StorageLive(_16);
92+
_16 = _5;
93+
StorageLive(_17);
94+
- _17 = _7;
95+
- _15 = Eq(move _16, move _17);
96+
+ _17 = _8;
97+
+ _15 = Eq(_5, _8);
98+
StorageDead(_17);
99+
StorageDead(_16);
100+
StorageLive(_18);
101+
StorageLive(_19);
102+
- _19 = _7;
103+
+ _19 = _8;
104+
StorageLive(_20);
105+
- _20 = _10;
106+
- _18 = Eq(move _19, move _20);
107+
+ _20 = _11;
108+
+ _18 = Eq(_2, _3);
109+
StorageDead(_20);
110+
StorageDead(_19);
111+
StorageLive(_21);
112+
StorageLive(_22);
113+
- _22 = _10;
114+
+ _22 = _11;
115+
StorageLive(_23);
116+
_23 = _13;
117+
- _21 = Eq(move _22, move _23);
118+
+ _21 = Eq(_11, _13);
119+
StorageDead(_23);
120+
StorageDead(_22);
121+
_0 = const ();
122+
StorageDead(_21);
123+
StorageDead(_18);
124+
StorageDead(_15);
125+
- StorageDead(_13);
126+
+ nop;
127+
StorageDead(_10);
128+
StorageDead(_7);
129+
- StorageDead(_5);
130+
+ nop;
131+
return;
132+
}
133+
}
134+

tests/mir-opt/gvn.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,36 @@ fn generic_cast_metadata<T, A: ?Sized, B: ?Sized>(ps: *const [T], pa: *const A,
883883
}
884884
}
885885

886+
fn cast_pointer_eq(p1: *mut u8, p2: *mut u32, p3: *mut u32, p4: *mut [u32]) {
887+
// CHECK-LABEL: fn cast_pointer_eq
888+
// CHECK: debug p1 => [[P1:_1]];
889+
// CHECK: debug p2 => [[P2:_2]];
890+
// CHECK: debug p3 => [[P3:_3]];
891+
// CHECK: debug p4 => [[P4:_4]];
892+
893+
// CHECK: [[M1:_.+]] = [[P1]] as *const u32 (PtrToPtr);
894+
// CHECK: [[M2:_.+]] = [[P2]] as *const u32 (PtrToPtr);
895+
// CHECK: [[M3:_.+]] = [[P3]] as *const u32 (PtrToPtr);
896+
// CHECK: [[M4:_.+]] = [[P4]] as *const u32 (PtrToPtr);
897+
let m1 = p1 as *const u32;
898+
let m2 = p2 as *const u32;
899+
let m3 = p3 as *const u32;
900+
let m4 = p4 as *const u32;
901+
902+
// CHECK-NOT: Eq
903+
// CHECK: Eq([[M1]], [[M2]])
904+
// CHECK-NOT: Eq
905+
// CHECK: Eq([[P2]], [[P3]])
906+
// CHECK-NOT: Eq
907+
// CHECK: Eq([[M3]], [[M4]])
908+
// CHECK-NOT: Eq
909+
let eq_different_thing = m1 == m2;
910+
let eq_optimize = m2 == m3;
911+
let eq_thin_fat = m3 == m4;
912+
913+
// CHECK: _0 = const ();
914+
}
915+
886916
fn main() {
887917
subexpression_elimination(2, 4, 5);
888918
wrap_unwrap(5);
@@ -950,3 +980,4 @@ fn identity<T>(x: T) -> T {
950980
// EMIT_MIR gvn.manual_slice_mut_len.GVN.diff
951981
// EMIT_MIR gvn.array_len.GVN.diff
952982
// EMIT_MIR gvn.generic_cast_metadata.GVN.diff
983+
// EMIT_MIR gvn.cast_pointer_eq.GVN.diff

0 commit comments

Comments
 (0)