xref: /llvm-project/llvm/test/Transforms/InstSimplify/uscmp.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3
4define i8 @scmp_lt() {
5; CHECK-LABEL: define i8 @scmp_lt() {
6; CHECK-NEXT:    ret i8 -1
7;
8  %1 = call i8 @llvm.scmp(i32 -7, i32 3)
9  ret i8 %1
10}
11
12define i8 @scmp_eq() {
13; CHECK-LABEL: define i8 @scmp_eq() {
14; CHECK-NEXT:    ret i8 0
15;
16  %1 = call i8 @llvm.scmp(i32 2, i32 2)
17  ret i8 %1
18}
19
20define i8 @scmp_gt() {
21; CHECK-LABEL: define i8 @scmp_gt() {
22; CHECK-NEXT:    ret i8 1
23;
24  %1 = call i8 @llvm.scmp(i32 2, i32 -7)
25  ret i8 %1
26}
27
28define i8 @ucmp_lt() {
29; CHECK-LABEL: define i8 @ucmp_lt() {
30; CHECK-NEXT:    ret i8 -1
31;
32  %1 = call i8 @llvm.ucmp(i32 7, i32 12)
33  ret i8 %1
34}
35
36define i2 @ucmp_eq() {
37; CHECK-LABEL: define i2 @ucmp_eq() {
38; CHECK-NEXT:    ret i2 0
39;
40  %1 = call i2 @llvm.ucmp(i32 12, i32 12)
41  ret i2 %1
42}
43
44define i100 @ucmp_gt() {
45; CHECK-LABEL: define i100 @ucmp_gt() {
46; CHECK-NEXT:    ret i100 1
47;
48  %1 = call i100 @llvm.ucmp(i32 7, i32 3)
49  ret i100 %1
50}
51
52define i8 @ucmp_poison() {
53; CHECK-LABEL: define i8 @ucmp_poison() {
54; CHECK-NEXT:    ret i8 poison
55;
56  %1 = call i8 @llvm.ucmp(i32 poison, i32 5)
57  ret i8 %1
58}
59
60define i8 @scmp_poison() {
61; CHECK-LABEL: define i8 @scmp_poison() {
62; CHECK-NEXT:    ret i8 poison
63;
64  %1 = call i8 @llvm.scmp(i32 0, i32 poison)
65  ret i8 %1
66}
67
68define i8 @scmp_undef() {
69; CHECK-LABEL: define i8 @scmp_undef() {
70; CHECK-NEXT:    ret i8 0
71;
72  %1 = call i8 @llvm.scmp(i32 undef, i32 -12)
73  ret i8 %1
74}
75
76define i8 @ucmp_undef() {
77; CHECK-LABEL: define i8 @ucmp_undef() {
78; CHECK-NEXT:    ret i8 0
79;
80  %1 = call i8 @llvm.ucmp(i32 2, i32 undef)
81  ret i8 %1
82}
83
84define <4 x i8> @ucmp_lt_splat() {
85; CHECK-LABEL: define <4 x i8> @ucmp_lt_splat() {
86; CHECK-NEXT:    ret <4 x i8> splat (i8 -1)
87;
88  %1 = call <4 x i8> @llvm.ucmp(<4 x i32> splat(i32 1), <4 x i32> splat(i32 3))
89  ret <4 x i8> %1
90}
91
92define <4 x i8> @scmp_nonsplat() {
93; CHECK-LABEL: define <4 x i8> @scmp_nonsplat() {
94; CHECK-NEXT:    ret <4 x i8> <i8 1, i8 0, i8 1, i8 -1>
95;
96  %1 = call <4 x i8> @llvm.scmp(<4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32> <i32 -1, i32 1, i32 -2, i32 4>)
97  ret <4 x i8> %1
98}
99
100define i8 @scmp_with_itself(i32 %x) {
101; CHECK-LABEL: define i8 @scmp_with_itself(
102; CHECK-SAME: i32 [[X:%.*]]) {
103; CHECK-NEXT:    ret i8 0
104;
105  %1 = call i8 @llvm.scmp(i32 %x, i32 %x)
106  ret i8 %1
107}
108
109define <4 x i8> @ucmp_vec_with_itself(<4 x i32> %x) {
110; CHECK-LABEL: define <4 x i8> @ucmp_vec_with_itself(
111; CHECK-SAME: <4 x i32> [[X:%.*]]) {
112; CHECK-NEXT:    ret <4 x i8> zeroinitializer
113;
114  %1 = call <4 x i8> @llvm.scmp(<4 x i32> %x, <4 x i32> %x)
115  ret <4 x i8> %1
116}
117
118define i8 @scmp_known_gt(i32 %x, i32 %y) {
119; CHECK-LABEL: define i8 @scmp_known_gt(
120; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
121; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
122; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
123; CHECK-NEXT:    ret i8 1
124;
125  %1 = icmp sgt i32 %x, %y
126  call void @llvm.assume(i1 %1)
127
128  %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
129  ret i8 %2
130}
131
132define i8 @scmp_known_eq(i32 %x, i32 %y) {
133; CHECK-LABEL: define i8 @scmp_known_eq(
134; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
135; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[X]], [[Y]]
136; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
137; CHECK-NEXT:    ret i8 0
138;
139  %1 = icmp eq i32 %x, %y
140  call void @llvm.assume(i1 %1)
141
142  %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
143  ret i8 %2
144}
145
146define i8 @scmp_known_lt(i32 %x, i32 %y) {
147; CHECK-LABEL: define i8 @scmp_known_lt(
148; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
149; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X]], [[Y]]
150; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
151; CHECK-NEXT:    ret i8 -1
152;
153  %1 = icmp slt i32 %x, %y
154  call void @llvm.assume(i1 %1)
155
156  %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
157  ret i8 %2
158}
159
160define i8 @ucmp_known_gt(i32 %x, i32 %y) {
161; CHECK-LABEL: define i8 @ucmp_known_gt(
162; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
163; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[X]], [[Y]]
164; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
165; CHECK-NEXT:    ret i8 1
166;
167  %1 = icmp ugt i32 %x, %y
168  call void @llvm.assume(i1 %1)
169
170  %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
171  ret i8 %2
172}
173
174define i8 @ucmp_known_eq(i32 %x, i32 %y) {
175; CHECK-LABEL: define i8 @ucmp_known_eq(
176; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
177; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[X]], [[Y]]
178; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
179; CHECK-NEXT:    ret i8 0
180;
181  %1 = icmp eq i32 %x, %y
182  call void @llvm.assume(i1 %1)
183
184  %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
185  ret i8 %2
186}
187
188define i8 @ucmp_known_lt(i32 %x, i32 %y) {
189; CHECK-LABEL: define i8 @ucmp_known_lt(
190; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
191; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X]], [[Y]]
192; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
193; CHECK-NEXT:    ret i8 -1
194;
195  %1 = icmp ult i32 %x, %y
196  call void @llvm.assume(i1 %1)
197
198  %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
199  ret i8 %2
200}
201
202define i8 @ucmp_with_addition(i32 %x) {
203; CHECK-LABEL: define i8 @ucmp_with_addition(
204; CHECK-SAME: i32 [[X:%.*]]) {
205; CHECK-NEXT:    ret i8 -1
206;
207  %1 = add nuw i32 %x, 1
208  %2 = call i8 @llvm.ucmp(i32 %x, i32 %1)
209  ret i8 %2
210}
211
212define i8 @ucmp_with_addition2(i32 %x) {
213; CHECK-LABEL: define i8 @ucmp_with_addition2(
214; CHECK-SAME: i32 [[X:%.*]]) {
215; CHECK-NEXT:    ret i8 1
216;
217  %1 = add nuw i32 %x, 1
218  %2 = call i8 @llvm.ucmp(i32 %1, i32 %x)
219  ret i8 %2
220}
221
222define <4 x i8> @ucmp_with_addition_vec(<4 x i32> %x) {
223; CHECK-LABEL: define <4 x i8> @ucmp_with_addition_vec(
224; CHECK-SAME: <4 x i32> [[X:%.*]]) {
225; CHECK-NEXT:    ret <4 x i8> splat (i8 -1)
226;
227  %1 = add nuw <4 x i32> %x, splat(i32 1)
228  %2 = call <4 x i8> @llvm.ucmp(<4 x i32> %x, <4 x i32> %1)
229  ret <4 x i8> %2
230}
231
232define i1 @scmp_eq_4(i32 %x, i32 %y) {
233; CHECK-LABEL: define i1 @scmp_eq_4(
234; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
235; CHECK-NEXT:    ret i1 false
236;
237  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
238  %2 = icmp eq i8 %1, 4
239  ret i1 %2
240}
241
242define i1 @ucmp_ne_negative_2(i32 %x, i32 %y) {
243; CHECK-LABEL: define i1 @ucmp_ne_negative_2(
244; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
245; CHECK-NEXT:    ret i1 true
246;
247  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
248  %2 = icmp ne i8 %1, -2
249  ret i1 %2
250}
251
252; Negative case: mismatched signedness of predicates
253define i8 @scmp_known_ugt(i32 %x, i32 %y) {
254; CHECK-LABEL: define i8 @scmp_known_ugt(
255; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
256; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[X]], [[Y]]
257; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
258; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
259; CHECK-NEXT:    ret i8 [[TMP2]]
260;
261  %1 = icmp ugt i32 %x, %y
262  call void @llvm.assume(i1 %1)
263
264  %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
265  ret i8 %2
266}
267
268define i8 @scmp_known_ult(i32 %x, i32 %y) {
269; CHECK-LABEL: define i8 @scmp_known_ult(
270; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
271; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X]], [[Y]]
272; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
273; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
274; CHECK-NEXT:    ret i8 [[TMP2]]
275;
276  %1 = icmp ult i32 %x, %y
277  call void @llvm.assume(i1 %1)
278
279  %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
280  ret i8 %2
281}
282
283define i8 @ucmp_known_sgt(i32 %x, i32 %y) {
284; CHECK-LABEL: define i8 @ucmp_known_sgt(
285; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
286; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
287; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
288; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
289; CHECK-NEXT:    ret i8 [[TMP2]]
290;
291  %1 = icmp sgt i32 %x, %y
292  call void @llvm.assume(i1 %1)
293
294  %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
295  ret i8 %2
296}
297
298define i8 @ucmp_known_slt(i32 %x, i32 %y) {
299; CHECK-LABEL: define i8 @ucmp_known_slt(
300; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
301; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X]], [[Y]]
302; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
303; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
304; CHECK-NEXT:    ret i8 [[TMP2]]
305;
306  %1 = icmp slt i32 %x, %y
307  call void @llvm.assume(i1 %1)
308
309  %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
310  ret i8 %2
311}
312
313; Negative case: no nuw flag
314define i8 @ucmp_with_addition_no_nuw(i32 %x) {
315; CHECK-LABEL: define i8 @ucmp_with_addition_no_nuw(
316; CHECK-SAME: i32 [[X:%.*]]) {
317; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X]], 1
318; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[TMP1]])
319; CHECK-NEXT:    ret i8 [[TMP2]]
320;
321  %1 = add i32 %x, 1
322  %2 = call i8 @llvm.ucmp(i32 %x, i32 %1)
323  ret i8 %2
324}
325