Skip to content

Commit dc37e37

Browse files
committed
Add a codegen test for comparisons of 2-tuples of primitives
The operators are all overridden in full for tuples, so those parts pass easily, but they're worth pinning. Going via `Ord::cmp`, though, doesn't optimize away for anything but `cmp`+`is_le`. So this leaves `FIXME`s in the tests for the others.
1 parent 5348a89 commit dc37e37

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// compile-flags: -C opt-level=1 -Z merge-functions=disabled
2+
// min-llvm-version: 15.0
3+
// only-x86_64
4+
5+
#![crate_type = "lib"]
6+
7+
use std::cmp::Ordering;
8+
9+
type TwoTuple = (i16, u16);
10+
11+
//
12+
// The operators are all overridden directly, so should optimize easily.
13+
//
14+
15+
// CHECK-LABEL: @check_lt_direct
16+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
17+
#[no_mangle]
18+
pub fn check_lt_direct(a: TwoTuple, b: TwoTuple) -> bool {
19+
// CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
20+
// CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
21+
// CHECK-DAG: %[[CMP1:.+]] = icmp ult i16 %[[A1]], %[[B1]]
22+
// CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
23+
// CHECK: ret i1 %[[R]]
24+
a < b
25+
}
26+
27+
// CHECK-LABEL: @check_le_direct
28+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
29+
#[no_mangle]
30+
pub fn check_le_direct(a: TwoTuple, b: TwoTuple) -> bool {
31+
// CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
32+
// CHECK-DAG: %[[CMP0:.+]] = icmp sle i16 %[[A0]], %[[B0]]
33+
// CHECK-DAG: %[[CMP1:.+]] = icmp ule i16 %[[A1]], %[[B1]]
34+
// CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
35+
// CHECK: ret i1 %[[R]]
36+
a <= b
37+
}
38+
39+
// CHECK-LABEL: @check_gt_direct
40+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
41+
#[no_mangle]
42+
pub fn check_gt_direct(a: TwoTuple, b: TwoTuple) -> bool {
43+
// CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
44+
// CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
45+
// CHECK-DAG: %[[CMP1:.+]] = icmp ugt i16 %[[A1]], %[[B1]]
46+
// CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
47+
// CHECK: ret i1 %[[R]]
48+
a > b
49+
}
50+
51+
// CHECK-LABEL: @check_ge_direct
52+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
53+
#[no_mangle]
54+
pub fn check_ge_direct(a: TwoTuple, b: TwoTuple) -> bool {
55+
// CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
56+
// CHECK-DAG: %[[CMP0:.+]] = icmp sge i16 %[[A0]], %[[B0]]
57+
// CHECK-DAG: %[[CMP1:.+]] = icmp uge i16 %[[A1]], %[[B1]]
58+
// CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
59+
// CHECK: ret i1 %[[R]]
60+
a >= b
61+
}
62+
63+
//
64+
// These ones are harder, since there are more intermediate values to remove.
65+
//
66+
// `<` seems to be getting lucky right now, so test that doesn't regress.
67+
//
68+
// The others, however, aren't managing to optimize away the extra `select`s yet.
69+
// See <https://github.com/rust-lang/rust/issues/106107> for more about this.
70+
//
71+
72+
// CHECK-LABEL: @check_lt_via_cmp
73+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
74+
#[no_mangle]
75+
pub fn check_lt_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
76+
// CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
77+
// CHECK-DAG: %[[CMP0:.+]] = icmp slt i16 %[[A0]], %[[B0]]
78+
// CHECK-DAG: %[[CMP1:.+]] = icmp ult i16 %[[A1]], %[[B1]]
79+
// CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
80+
// CHECK: ret i1 %[[R]]
81+
Ord::cmp(&a, &b).is_lt()
82+
}
83+
84+
// CHECK-LABEL: @check_le_via_cmp
85+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
86+
#[no_mangle]
87+
pub fn check_le_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
88+
// FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
89+
// FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sle i16 %[[A0]], %[[B0]]
90+
// FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp ule i16 %[[A1]], %[[B1]]
91+
// FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
92+
// FIXME-CHECK: ret i1 %[[R]]
93+
Ord::cmp(&a, &b).is_le()
94+
}
95+
96+
// CHECK-LABEL: @check_gt_via_cmp
97+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
98+
#[no_mangle]
99+
pub fn check_gt_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
100+
// FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
101+
// FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sgt i16 %[[A0]], %[[B0]]
102+
// FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp ugt i16 %[[A1]], %[[B1]]
103+
// FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
104+
// FIXME-CHECK: ret i1 %[[R]]
105+
Ord::cmp(&a, &b).is_gt()
106+
}
107+
108+
// CHECK-LABEL: @check_ge_via_cmp
109+
// CHECK-SAME: (i16 noundef %[[A0:.+]], i16 noundef %[[A1:.+]], i16 noundef %[[B0:.+]], i16 noundef %[[B1:.+]])
110+
#[no_mangle]
111+
pub fn check_ge_via_cmp(a: TwoTuple, b: TwoTuple) -> bool {
112+
// FIXME-CHECK-DAG: %[[EQ:.+]] = icmp eq i16 %[[A0]], %[[B0]]
113+
// FIXME-CHECK-DAG: %[[CMP0:.+]] = icmp sge i16 %[[A0]], %[[B0]]
114+
// FIXME-CHECK-DAG: %[[CMP1:.+]] = icmp uge i16 %[[A1]], %[[B1]]
115+
// FIXME-CHECK: %[[R:.+]] = select i1 %[[EQ]], i1 %[[CMP1]], i1 %[[CMP0]]
116+
// FIXME-CHECK: ret i1 %[[R]]
117+
Ord::cmp(&a, &b).is_ge()
118+
}

0 commit comments

Comments
 (0)