ELF: Have __rela_iplt_{start,end} surround .rela.iplt with --pack-dyn-relocs=android.
[llvm-project.git] / llvm / test / Transforms / InstCombine / ucmp.ll
blob2d5036019740cd5f4793b3d51147836f39609ffe
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare void @use(i8 %value)
6 define i1 @ucmp_eq_0(i32 %x, i32 %y) {
7 ; CHECK-LABEL: define i1 @ucmp_eq_0(
8 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
9 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[X]], [[Y]]
10 ; CHECK-NEXT:    ret i1 [[TMP2]]
12   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
13   %2 = icmp eq i8 %1, 0
14   ret i1 %2
17 define i1 @ucmp_ne_0(i32 %x, i32 %y) {
18 ; CHECK-LABEL: define i1 @ucmp_ne_0(
19 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
20 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[X]], [[Y]]
21 ; CHECK-NEXT:    ret i1 [[TMP2]]
23   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
24   %2 = icmp ne i8 %1, 0
25   ret i1 %2
28 define i1 @ucmp_eq_1(i32 %x, i32 %y) {
29 ; CHECK-LABEL: define i1 @ucmp_eq_1(
30 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
31 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
32 ; CHECK-NEXT:    ret i1 [[TMP2]]
34   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
35   %2 = icmp eq i8 %1, 1
36   ret i1 %2
39 define i1 @ucmp_ne_1(i32 %x, i32 %y) {
40 ; CHECK-LABEL: define i1 @ucmp_ne_1(
41 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
42 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
43 ; CHECK-NEXT:    ret i1 [[TMP2]]
45   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
46   %2 = icmp ne i8 %1, 1
47   ret i1 %2
50 define i1 @ucmp_eq_negative_1(i32 %x, i32 %y) {
51 ; CHECK-LABEL: define i1 @ucmp_eq_negative_1(
52 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
53 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
54 ; CHECK-NEXT:    ret i1 [[TMP2]]
56   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
57   %2 = icmp eq i8 %1, -1
58   ret i1 %2
61 define i1 @ucmp_ne_negative_1(i32 %x, i32 %y) {
62 ; CHECK-LABEL: define i1 @ucmp_ne_negative_1(
63 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
64 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
65 ; CHECK-NEXT:    ret i1 [[TMP2]]
67   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
68   %2 = icmp ne i8 %1, -1
69   ret i1 %2
72 define i1 @ucmp_sgt_0(i32 %x, i32 %y) {
73 ; CHECK-LABEL: define i1 @ucmp_sgt_0(
74 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
75 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
76 ; CHECK-NEXT:    ret i1 [[TMP2]]
78   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
79   %2 = icmp sgt i8 %1, 0
80   ret i1 %2
83 define i1 @ucmp_sgt_neg_1(i32 %x, i32 %y) {
84 ; CHECK-LABEL: define i1 @ucmp_sgt_neg_1(
85 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
86 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
87 ; CHECK-NEXT:    ret i1 [[TMP2]]
89   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
90   %2 = icmp sgt i8 %1, -1
91   ret i1 %2
94 define i1 @ucmp_sge_0(i32 %x, i32 %y) {
95 ; CHECK-LABEL: define i1 @ucmp_sge_0(
96 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
97 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
98 ; CHECK-NEXT:    ret i1 [[TMP2]]
100   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
101   %2 = icmp sge i8 %1, 0
102   ret i1 %2
105 define i1 @ucmp_sge_1(i32 %x, i32 %y) {
106 ; CHECK-LABEL: define i1 @ucmp_sge_1(
107 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
108 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
109 ; CHECK-NEXT:    ret i1 [[TMP2]]
111   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
112   %2 = icmp sge i8 %1, 1
113   ret i1 %2
116 define i1 @ucmp_slt_0(i32 %x, i32 %y) {
117 ; CHECK-LABEL: define i1 @ucmp_slt_0(
118 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
119 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
120 ; CHECK-NEXT:    ret i1 [[TMP2]]
122   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
123   %2 = icmp slt i8 %1, 0
124   ret i1 %2
127 define i1 @ucmp_slt_1(i32 %x, i32 %y) {
128 ; CHECK-LABEL: define i1 @ucmp_slt_1(
129 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
130 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
131 ; CHECK-NEXT:    ret i1 [[TMP2]]
133   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
134   %2 = icmp slt i8 %1, 1
135   ret i1 %2
138 define i1 @ucmp_sle_0(i32 %x, i32 %y) {
139 ; CHECK-LABEL: define i1 @ucmp_sle_0(
140 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
141 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
142 ; CHECK-NEXT:    ret i1 [[TMP2]]
144   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
145   %2 = icmp sle i8 %1, 0
146   ret i1 %2
149 define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) {
150 ; CHECK-LABEL: define i1 @ucmp_sle_neg_1(
151 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
152 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
153 ; CHECK-NEXT:    ret i1 [[TMP2]]
155   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
156   %2 = icmp sle i8 %1, -1
157   ret i1 %2
160 ; ucmp(x, y) u< C => x u>= y when C u> 1 and C != -1
161 define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) {
162 ; CHECK-LABEL: define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(
163 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
164 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[X]], [[Y]]
165 ; CHECK-NEXT:    ret i1 [[TMP1]]
167   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
168   %2 = icmp ult i8 %1, 4
169   ret i1 %2
172 ; ucmp(x, y) u> C => x u< y when C != 0 and C != -1
173 define i1 @ucmp_ugt_const_not_0_or_neg1(i32 %x, i32 %y) {
174 ; CHECK-LABEL: define i1 @ucmp_ugt_const_not_0_or_neg1(
175 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
176 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
177 ; CHECK-NEXT:    ret i1 [[TMP2]]
179   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
180   %2 = icmp ugt i8 %1, 12
181   ret i1 %2
184 ; ========== Fold -ucmp(x, y) => ucmp(y, x) ==========
185 define i8 @ucmp_negated(i32 %x, i32 %y) {
186 ; CHECK-LABEL: define i8 @ucmp_negated(
187 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
188 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[Y]], i32 [[X]])
189 ; CHECK-NEXT:    ret i8 [[TMP2]]
191   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
192   %2 = sub i8 0, %1
193   ret i8 %2
196 ; Negative test: do not fold if the original ucmp result is already used
197 define i8 @ucmp_negated_multiuse(i32 %x, i32 %y) {
198 ; CHECK-LABEL: define i8 @ucmp_negated_multiuse(
199 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
200 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
201 ; CHECK-NEXT:    call void @use(i8 [[TMP1]])
202 ; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i8 0, [[TMP1]]
203 ; CHECK-NEXT:    ret i8 [[TMP2]]
205   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
206   call void @use(i8 %1)
207   %2 = sub i8 0, %1
208   ret i8 %2
211 ; Fold ((x u< y) ? -1 : (x != y)) into ucmp(x, y)
212 define i8 @ucmp_from_select_lt(i32 %x, i32 %y) {
213 ; CHECK-LABEL: define i8 @ucmp_from_select_lt(
214 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
215 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
216 ; CHECK-NEXT:    ret i8 [[R]]
218   %ne_bool = icmp ne i32 %x, %y
219   %ne = zext i1 %ne_bool to i8
220   %lt = icmp ult i32 %x, %y
221   %r = select i1 %lt, i8 -1, i8 %ne
222   ret i8 %r
225 ; Fold (x u< y) ? -1 : zext(x u> y) into ucmp(x, y)
226 define i8 @ucmp_from_select_lt_and_gt(i32 %x, i32 %y) {
227 ; CHECK-LABEL: define i8 @ucmp_from_select_lt_and_gt(
228 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
229 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
230 ; CHECK-NEXT:    ret i8 [[R]]
232   %gt_bool = icmp ugt i32 %x, %y
233   %gt = zext i1 %gt_bool to i8
234   %lt = icmp ult i32 %x, %y
235   %r = select i1 %lt, i8 -1, i8 %gt
236   ret i8 %r
239 ; Vector version
240 define <4 x i8> @ucmp_from_select_vec_lt(<4 x i32> %x, <4 x i32> %y) {
241 ; CHECK-LABEL: define <4 x i8> @ucmp_from_select_vec_lt(
242 ; CHECK-SAME: <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]]) {
243 ; CHECK-NEXT:    [[R:%.*]] = call <4 x i8> @llvm.ucmp.v4i8.v4i32(<4 x i32> [[X]], <4 x i32> [[Y]])
244 ; CHECK-NEXT:    ret <4 x i8> [[R]]
246   %ne_bool = icmp ne <4 x i32> %x, %y
247   %ne = zext <4 x i1> %ne_bool to <4 x i8>
248   %lt = icmp ult <4 x i32> %x, %y
249   %r = select <4 x i1> %lt, <4 x i8> splat(i8 -1), <4 x i8> %ne
250   ret <4 x i8> %r
253 ; Commuted operands
254 define i8 @ucmp_from_select_lt_commuted_ops1(i32 %x, i32 %y) {
255 ; CHECK-LABEL: define i8 @ucmp_from_select_lt_commuted_ops1(
256 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
257 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
258 ; CHECK-NEXT:    ret i8 [[R]]
260   %ne_bool = icmp ne i32 %y, %x
261   %ne = zext i1 %ne_bool to i8
262   %lt = icmp ult i32 %x, %y
263   %r = select i1 %lt, i8 -1, i8 %ne
264   ret i8 %r
267 define i8 @ucmp_from_select_lt_commuted_ops2(i32 %x, i32 %y) {
268 ; CHECK-LABEL: define i8 @ucmp_from_select_lt_commuted_ops2(
269 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
270 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
271 ; CHECK-NEXT:    ret i8 [[R]]
273   %ne_bool = icmp ne i32 %x, %y
274   %ne = zext i1 %ne_bool to i8
275   %lt = icmp ugt i32 %y, %x
276   %r = select i1 %lt, i8 -1, i8 %ne
277   ret i8 %r
280 ; Negative test: false value of the select is not `icmp ne x, y`
281 define i8 @ucmp_from_select_lt_neg1(i32 %x, i32 %y) {
282 ; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg1(
283 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
284 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp eq i32 [[X]], [[Y]]
285 ; CHECK-NEXT:    [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8
286 ; CHECK-NEXT:    [[LT:%.*]] = icmp ult i32 [[X]], [[Y]]
287 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[LT]], i8 -1, i8 [[NE]]
288 ; CHECK-NEXT:    ret i8 [[R]]
290   %ne_bool = icmp eq i32 %x, %y
291   %ne = zext i1 %ne_bool to i8
292   %lt = icmp ult i32 %x, %y
293   %r = select i1 %lt, i8 -1, i8 %ne
294   ret i8 %r
297 ; Negative test: true value of select is not -1
298 define i8 @ucmp_from_select_lt_neg2(i32 %x, i32 %y) {
299 ; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg2(
300 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
301 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
302 ; CHECK-NEXT:    [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8
303 ; CHECK-NEXT:    [[LT:%.*]] = icmp ult i32 [[X]], [[Y]]
304 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[LT]], i8 2, i8 [[NE]]
305 ; CHECK-NEXT:    ret i8 [[R]]
307   %ne_bool = icmp ne i32 %x, %y
308   %ne = zext i1 %ne_bool to i8
309   %lt = icmp ult i32 %x, %y
310   %r = select i1 %lt, i8 2, i8 %ne
311   ret i8 %r
314 ; Negative test: false value of select is sign-extended instead of zero-extended
315 define i8 @ucmp_from_select_lt_neg3(i32 %x, i32 %y) {
316 ; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg3(
317 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
318 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
319 ; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NE_BOOL]] to i8
320 ; CHECK-NEXT:    ret i8 [[R]]
322   %ne_bool = icmp ne i32 %x, %y
323   %ne = sext i1 %ne_bool to i8
324   %lt = icmp ult i32 %x, %y
325   %r = select i1 %lt, i8 -1, i8 %ne
326   ret i8 %r
329 ; Negative test: condition of select is not (x u< y)
330 define i8 @ucmp_from_select_lt_neg4(i32 %x, i32 %y) {
331 ; CHECK-LABEL: define i8 @ucmp_from_select_lt_neg4(
332 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
333 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
334 ; CHECK-NEXT:    [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8
335 ; CHECK-NEXT:    [[LT_NOT:%.*]] = icmp ugt i32 [[X]], [[Y]]
336 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[LT_NOT]], i8 [[NE]], i8 -1
337 ; CHECK-NEXT:    ret i8 [[R]]
339   %ne_bool = icmp ne i32 %x, %y
340   %ne = zext i1 %ne_bool to i8
341   %lt = icmp ule i32 %x, %y
342   %r = select i1 %lt, i8 -1, i8 %ne
343   ret i8 %r
346 ; Fold (x u<= y) ? sext(x != y) : 1 into ucmp(x, y)
347 define i8 @ucmp_from_select_le(i32 %x, i32 %y) {
348 ; CHECK-LABEL: define i8 @ucmp_from_select_le(
349 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
350 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
351 ; CHECK-NEXT:    ret i8 [[R]]
353   %ne_bool = icmp ne i32 %x, %y
354   %ne = sext i1 %ne_bool to i8
355   %le = icmp ule i32 %x, %y
356   %r = select i1 %le, i8 %ne, i8 1
357   ret i8 %r
360 ; Negative test: condition of select is not (x u<= y)
361 define i8 @ucmp_from_select_le_neg1(i32 %x, i32 %y) {
362 ; CHECK-LABEL: define i8 @ucmp_from_select_le_neg1(
363 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
364 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ult i32 [[X]], [[Y]]
365 ; CHECK-NEXT:    [[NE:%.*]] = sext i1 [[NE_BOOL]] to i8
366 ; CHECK-NEXT:    [[LE_NOT:%.*]] = icmp ult i32 [[X]], [[Y]]
367 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[LE_NOT]], i8 1, i8 [[NE]]
368 ; CHECK-NEXT:    ret i8 [[R]]
370   %ne_bool = icmp ult i32 %x, %y
371   %ne = sext i1 %ne_bool to i8
372   %le = icmp uge i32 %x, %y
373   %r = select i1 %le, i8 %ne, i8 1
374   ret i8 %r
377 ; Negative test: true value of select is zero-extended instead of sign-extended
378 define i8 @ucmp_from_select_le_neg2(i32 %x, i32 %y) {
379 ; CHECK-LABEL: define i8 @ucmp_from_select_le_neg2(
380 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
381 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
382 ; CHECK-NEXT:    [[R:%.*]] = zext i1 [[NE_BOOL]] to i8
383 ; CHECK-NEXT:    ret i8 [[R]]
385   %ne_bool = icmp ne i32 %x, %y
386   %ne = zext i1 %ne_bool to i8
387   %le = icmp ule i32 %x, %y
388   %r = select i1 %le, i8 %ne, i8 1
389   ret i8 %r
392 ; Negative test: true value is not x != y
393 define i8 @ucmp_from_select_le_neg3(i32 %x, i32 %y) {
394 ; CHECK-LABEL: define i8 @ucmp_from_select_le_neg3(
395 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
396 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp sgt i32 [[X]], [[Y]]
397 ; CHECK-NEXT:    [[NE:%.*]] = sext i1 [[NE_BOOL]] to i8
398 ; CHECK-NEXT:    [[LE_NOT:%.*]] = icmp ugt i32 [[X]], [[Y]]
399 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[LE_NOT]], i8 1, i8 [[NE]]
400 ; CHECK-NEXT:    ret i8 [[R]]
402   %ne_bool = icmp sgt i32 %x, %y
403   %ne = sext i1 %ne_bool to i8
404   %le = icmp ule i32 %x, %y
405   %r = select i1 %le, i8 %ne, i8 1
406   ret i8 %r
409 ; Negative test: false value is not 1
410 define i8 @ucmp_from_select_le_neg4(i32 %x, i32 %y) {
411 ; CHECK-LABEL: define i8 @ucmp_from_select_le_neg4(
412 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
413 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
414 ; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NE_BOOL]] to i8
415 ; CHECK-NEXT:    ret i8 [[R]]
417   %ne_bool = icmp ne i32 %x, %y
418   %ne = sext i1 %ne_bool to i8
419   %le = icmp ule i32 %x, %y
420   %r = select i1 %le, i8 %ne, i8 -1
421   ret i8 %r
424 ; Fold (x u>= y) ? zext(x != y) : -1 into ucmp(x, y)
425 define i8 @ucmp_from_select_ge(i32 %x, i32 %y) {
426 ; CHECK-LABEL: define i8 @ucmp_from_select_ge(
427 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
428 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
429 ; CHECK-NEXT:    ret i8 [[R]]
431   %ne_bool = icmp ne i32 %x, %y
432   %ne = zext i1 %ne_bool to i8
433   %ge = icmp uge i32 %x, %y
434   %r = select i1 %ge, i8 %ne, i8 -1
435   ret i8 %r
438 ; Commuted operands
439 define i8 @ucmp_from_select_ge_commuted_ops1(i32 %x, i32 %y) {
440 ; CHECK-LABEL: define i8 @ucmp_from_select_ge_commuted_ops1(
441 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
442 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
443 ; CHECK-NEXT:    ret i8 [[R]]
445   %ne_bool = icmp ne i32 %y, %x
446   %ne = zext i1 %ne_bool to i8
447   %ge = icmp uge i32 %x, %y
448   %r = select i1 %ge, i8 %ne, i8 -1
449   ret i8 %r
452 define i8 @ucmp_from_select_ge_commuted_ops2(i32 %x, i32 %y) {
453 ; CHECK-LABEL: define i8 @ucmp_from_select_ge_commuted_ops2(
454 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
455 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
456 ; CHECK-NEXT:    ret i8 [[R]]
458   %ne_bool = icmp ne i32 %x, %y
459   %ne = zext i1 %ne_bool to i8
460   %ge = icmp ule i32 %y, %x
461   %r = select i1 %ge, i8 %ne, i8 -1
462   ret i8 %r
465 ; Negative test: condition is not x u>= y
466 define i8 @ucmp_from_select_ge_neg1(i32 %x, i32 %y) {
467 ; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg1(
468 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
469 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
470 ; CHECK-NEXT:    [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8
471 ; CHECK-NEXT:    [[GE:%.*]] = icmp ult i32 [[X]], [[Y]]
472 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[GE]], i8 [[NE]], i8 -1
473 ; CHECK-NEXT:    ret i8 [[R]]
475   %ne_bool = icmp ne i32 %x, %y
476   %ne = zext i1 %ne_bool to i8
477   %ge = icmp ult i32 %x, %y
478   %r = select i1 %ge, i8 %ne, i8 -1
479   ret i8 %r
482 ; Negative test: true value is sign-extended instead of zero-extended
483 define i8 @ucmp_from_select_ge_neg2(i32 %x, i32 %y) {
484 ; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg2(
485 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
486 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
487 ; CHECK-NEXT:    [[R:%.*]] = sext i1 [[NE_BOOL]] to i8
488 ; CHECK-NEXT:    ret i8 [[R]]
490   %ne_bool = icmp ne i32 %x, %y
491   %ne = sext i1 %ne_bool to i8
492   %ge = icmp uge i32 %x, %y
493   %r = select i1 %ge, i8 %ne, i8 -1
494   ret i8 %r
497 ; Negative test: true value is not x != y
498 define i8 @ucmp_from_select_ge_neg3(i32 %x, i32 %y) {
499 ; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg3(
500 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
501 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp sgt i32 [[X]], [[Y]]
502 ; CHECK-NEXT:    [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8
503 ; CHECK-NEXT:    [[GE_NOT:%.*]] = icmp ult i32 [[X]], [[Y]]
504 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[GE_NOT]], i8 -1, i8 [[NE]]
505 ; CHECK-NEXT:    ret i8 [[R]]
507   %ne_bool = icmp sgt i32 %x, %y
508   %ne = zext i1 %ne_bool to i8
509   %ge = icmp uge i32 %x, %y
510   %r = select i1 %ge, i8 %ne, i8 -1
511   ret i8 %r
514 ; Negative test: false value is not -1
515 define i8 @ucmp_from_select_ge_neg4(i32 %x, i32 %y) {
516 ; CHECK-LABEL: define i8 @ucmp_from_select_ge_neg4(
517 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
518 ; CHECK-NEXT:    [[NE_BOOL:%.*]] = icmp ne i32 [[X]], [[Y]]
519 ; CHECK-NEXT:    [[NE:%.*]] = zext i1 [[NE_BOOL]] to i8
520 ; CHECK-NEXT:    [[GE_NOT:%.*]] = icmp ult i32 [[X]], [[Y]]
521 ; CHECK-NEXT:    [[R:%.*]] = select i1 [[GE_NOT]], i8 3, i8 [[NE]]
522 ; CHECK-NEXT:    ret i8 [[R]]
524   %ne_bool = icmp ne i32 %x, %y
525   %ne = zext i1 %ne_bool to i8
526   %ge = icmp uge i32 %x, %y
527   %r = select i1 %ge, i8 %ne, i8 3
528   ret i8 %r
531 ; Fold (x > y) ? 1 : sext(x < y)
532 define i8 @ucmp_from_select_gt_and_lt(i32 %x, i32 %y) {
533 ; CHECK-LABEL: define i8 @ucmp_from_select_gt_and_lt(
534 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
535 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
536 ; CHECK-NEXT:    ret i8 [[R]]
538   %lt_bool = icmp ult i32 %x, %y
539   %lt = sext i1 %lt_bool to i8
540   %gt = icmp ugt i32 %x, %y
541   %r = select i1 %gt, i8 1, i8 %lt
542   ret i8 %r
545 ; (x == y) ? 0 : (x u> y ? 1 : -1) into ucmp(x, y)
546 define i8 @scmp_from_select_eq_and_gt(i32 %x, i32 %y) {
547 ; CHECK-LABEL: define i8 @scmp_from_select_eq_and_gt(
548 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
549 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
550 ; CHECK-NEXT:    ret i8 [[R]]
552   %eq = icmp eq i32 %x, %y
553   %gt = icmp ugt i32 %x, %y
554   %sel1 = select i1 %gt, i8 1, i8 -1
555   %r = select i1 %eq, i8 0, i8 %sel1
556   ret i8 %r