[RISCV][VLOPT] Add vector narrowing integer right shift instructions to isSupportedIn...
[llvm-project.git] / llvm / test / CodeGen / AArch64 / cmp-select-sign.ll
blobb4f179e992a0d931df9f8f64e09d3cf52b11d668
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=arm64-apple-iphoneos -aarch64-enable-sink-fold=true -o - %s | FileCheck %s
4 define i3 @sign_i3(i3 %a) {
5 ; CHECK-LABEL: sign_i3:
6 ; CHECK:       // %bb.0:
7 ; CHECK-NEXT:    sbfx w8, w0, #2, #1
8 ; CHECK-NEXT:    orr w0, w8, #0x1
9 ; CHECK-NEXT:    ret
10   %c = icmp sgt i3 %a, -1
11   %res = select i1 %c, i3 1, i3 -1
12   ret i3 %res
15 define i4 @sign_i4(i4 %a) {
16 ; CHECK-LABEL: sign_i4:
17 ; CHECK:       // %bb.0:
18 ; CHECK-NEXT:    sbfx w8, w0, #3, #1
19 ; CHECK-NEXT:    orr w0, w8, #0x1
20 ; CHECK-NEXT:    ret
21   %c = icmp sgt i4 %a, -1
22   %res = select i1 %c, i4 1, i4 -1
23   ret i4 %res
26 define i8 @sign_i8(i8 %a) {
27 ; CHECK-LABEL: sign_i8:
28 ; CHECK:       // %bb.0:
29 ; CHECK-NEXT:    sbfx w8, w0, #7, #1
30 ; CHECK-NEXT:    orr w0, w8, #0x1
31 ; CHECK-NEXT:    ret
32   %c = icmp sgt i8 %a, -1
33   %res = select i1 %c, i8 1, i8 -1
34   ret i8 %res
37 define i16 @sign_i16(i16 %a) {
38 ; CHECK-LABEL: sign_i16:
39 ; CHECK:       // %bb.0:
40 ; CHECK-NEXT:    sbfx w8, w0, #15, #1
41 ; CHECK-NEXT:    orr w0, w8, #0x1
42 ; CHECK-NEXT:    ret
43   %c = icmp sgt i16 %a, -1
44   %res = select i1 %c, i16 1, i16 -1
45   ret i16 %res
48 define i32 @sign_i32(i32 %a) {
49 ; CHECK-LABEL: sign_i32:
50 ; CHECK:       // %bb.0:
51 ; CHECK-NEXT:    asr w8, w0, #31
52 ; CHECK-NEXT:    orr w0, w8, #0x1
53 ; CHECK-NEXT:    ret
54   %c = icmp sgt i32 %a, -1
55   %res = select i1 %c, i32 1, i32 -1
56   ret i32 %res
59 define i64 @sign_i64(i64 %a) {
60 ; CHECK-LABEL: sign_i64:
61 ; CHECK:       // %bb.0:
62 ; CHECK-NEXT:    asr x8, x0, #63
63 ; CHECK-NEXT:    orr x0, x8, #0x1
64 ; CHECK-NEXT:    ret
65   %c = icmp sgt i64 %a, -1
66   %res = select i1 %c, i64 1, i64 -1
67   ret i64 %res
71 define i64 @not_sign_i64(i64 %a) {
72 ; CHECK-LABEL: not_sign_i64:
73 ; CHECK:       // %bb.0:
74 ; CHECK-NEXT:    mov w8, #1 // =0x1
75 ; CHECK-NEXT:    cmp x0, #0
76 ; CHECK-NEXT:    cneg x0, x8, le
77 ; CHECK-NEXT:    ret
78   %c = icmp sgt i64 %a, 0
79   %res = select i1 %c, i64 1, i64 -1
80   ret i64 %res
83 define i64 @not_sign_i64_2(i64 %a) {
84 ; CHECK-LABEL: not_sign_i64_2:
85 ; CHECK:       // %bb.0:
86 ; CHECK-NEXT:    asr x0, x0, #63
87 ; CHECK-NEXT:    ret
88   %c = icmp sgt i64 %a, -1
89   %res = select i1 %c, i64 0, i64 -1
90   ret i64 %res
93 define i64 @not_sign_i64_3(i64 %a) {
94 ; CHECK-LABEL: not_sign_i64_3:
95 ; CHECK:       // %bb.0:
96 ; CHECK-NEXT:    mvn x8, x0
97 ; CHECK-NEXT:    lsr x0, x8, #63
98 ; CHECK-NEXT:    ret
99   %c = icmp sgt i64 %a, -1
100   %res = select i1 %c, i64 1, i64 0
101   ret i64 %res
104 define i64 @not_sign_i64_4(i64 %a) {
105 ; CHECK-LABEL: not_sign_i64_4:
106 ; CHECK:       // %bb.0:
107 ; CHECK-NEXT:    mov x0, #-1 // =0xffffffffffffffff
108 ; CHECK-NEXT:    ret
109   %c = icmp ugt i64 %a, -1
110   %res = select i1 %c, i64 1, i64 -1
111   ret i64 %res
114 define <7 x i8> @sign_7xi8(<7 x i8> %a) {
115 ; CHECK-LABEL: sign_7xi8:
116 ; CHECK:       // %bb.0:
117 ; CHECK-NEXT:    movi v1.8b, #1
118 ; CHECK-NEXT:    cmlt v0.8b, v0.8b, #0
119 ; CHECK-NEXT:    orr v0.8b, v0.8b, v1.8b
120 ; CHECK-NEXT:    ret
121   %c = icmp sgt <7 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
122   %res = select <7 x i1> %c, <7 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <7 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
123   ret <7 x i8> %res
126 define <8 x i8> @sign_8xi8(<8 x i8> %a) {
127 ; CHECK-LABEL: sign_8xi8:
128 ; CHECK:       // %bb.0:
129 ; CHECK-NEXT:    movi v1.8b, #1
130 ; CHECK-NEXT:    cmlt v0.8b, v0.8b, #0
131 ; CHECK-NEXT:    orr v0.8b, v0.8b, v1.8b
132 ; CHECK-NEXT:    ret
133   %c = icmp sgt <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
134   %res = select <8 x i1> %c, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
135   ret <8 x i8> %res
138 define <16 x i8> @sign_16xi8(<16 x i8> %a) {
139 ; CHECK-LABEL: sign_16xi8:
140 ; CHECK:       // %bb.0:
141 ; CHECK-NEXT:    movi v1.16b, #1
142 ; CHECK-NEXT:    cmlt v0.16b, v0.16b, #0
143 ; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
144 ; CHECK-NEXT:    ret
145   %c = icmp sgt <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
146   %res = select <16 x i1> %c, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
147   ret <16 x i8> %res
150 define <3 x i32> @sign_3xi32(<3 x i32> %a) {
151 ; CHECK-LABEL: sign_3xi32:
152 ; CHECK:       // %bb.0:
153 ; CHECK-NEXT:    cmlt v0.4s, v0.4s, #0
154 ; CHECK-NEXT:    orr v0.4s, #1
155 ; CHECK-NEXT:    ret
156   %c = icmp sgt <3 x i32> %a, <i32 -1, i32 -1, i32 -1>
157   %res = select <3 x i1> %c, <3 x i32> <i32 1, i32 1, i32 1>, <3 x i32> <i32 -1, i32 -1, i32 -1>
158   ret <3 x i32> %res
161 define <4 x i32> @sign_4xi32(<4 x i32> %a) {
162 ; CHECK-LABEL: sign_4xi32:
163 ; CHECK:       // %bb.0:
164 ; CHECK-NEXT:    cmlt v0.4s, v0.4s, #0
165 ; CHECK-NEXT:    orr v0.4s, #1
166 ; CHECK-NEXT:    ret
167   %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
168   %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
169   ret <4 x i32> %res
172 define <4 x i32> @sign_4xi32_multi_use(<4 x i32> %a) {
173 ; CHECK-LABEL: sign_4xi32_multi_use:
174 ; CHECK:       // %bb.0:
175 ; CHECK-NEXT:    sub sp, sp, #32
176 ; CHECK-NEXT:    str x30, [sp, #16] // 8-byte Folded Spill
177 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
178 ; CHECK-NEXT:    .cfi_offset w30, -16
179 ; CHECK-NEXT:    cmlt v1.4s, v0.4s, #0
180 ; CHECK-NEXT:    cmge v0.4s, v0.4s, #0
181 ; CHECK-NEXT:    xtn v0.4h, v0.4s
182 ; CHECK-NEXT:    orr v1.4s, #1
183 ; CHECK-NEXT:    str q1, [sp] // 16-byte Folded Spill
184 ; CHECK-NEXT:    bl use_4xi1
185 ; CHECK-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
186 ; CHECK-NEXT:    ldr x30, [sp, #16] // 8-byte Folded Reload
187 ; CHECK-NEXT:    add sp, sp, #32
188 ; CHECK-NEXT:    ret
189   %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
190   %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
191   call void @use_4xi1(<4 x i1> %c)
192   ret <4 x i32> %res
195 ; Second icmp operand breaks sign pattern.
196 define <4 x i32> @not_sign_4xi32(<4 x i32> %a) {
197 ; CHECK-LABEL: not_sign_4xi32:
198 ; CHECK:       // %bb.0:
199 ; CHECK-NEXT:    adrp x8, .LCPI16_0
200 ; CHECK-NEXT:    movi v2.4s, #1
201 ; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI16_0]
202 ; CHECK-NEXT:    cmgt v0.4s, v0.4s, v1.4s
203 ; CHECK-NEXT:    and v1.16b, v0.16b, v2.16b
204 ; CHECK-NEXT:    orn v0.16b, v1.16b, v0.16b
205 ; CHECK-NEXT:    ret
206   %c = icmp sgt <4 x i32> %a, <i32 1, i32 -1, i32 -1, i32 -1>
207   %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
208   ret <4 x i32> %res
211 ; First select operand breaks sign pattern.
212 define <4 x i32> @not_sign_4xi32_2(<4 x i32> %a) {
213 ; CHECK-LABEL: not_sign_4xi32_2:
214 ; CHECK:       // %bb.0:
215 ; CHECK-NEXT:    adrp x8, .LCPI17_0
216 ; CHECK-NEXT:    cmlt v0.4s, v0.4s, #0
217 ; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI17_0]
218 ; CHECK-NEXT:    orr v0.16b, v0.16b, v1.16b
219 ; CHECK-NEXT:    ret
220   %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
221   %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 -1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
222   ret <4 x i32> %res
225 ; Second select operand breaks sign pattern.
226 define <4 x i32> @not_sign_4xi32_3(<4 x i32> %a) {
227 ; CHECK-LABEL: not_sign_4xi32_3:
228 ; CHECK:       // %bb.0:
229 ; CHECK-NEXT:    adrp x8, .LCPI18_0
230 ; CHECK-NEXT:    cmge v0.4s, v0.4s, #0
231 ; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI18_0]
232 ; CHECK-NEXT:    bic v1.16b, v1.16b, v0.16b
233 ; CHECK-NEXT:    sub v0.4s, v1.4s, v0.4s
234 ; CHECK-NEXT:    ret
235   %c = icmp sgt <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
236   %res = select <4 x i1> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 1>
237   ret <4 x i32> %res
240 ; i65 is not legal.
241 define <4 x i65> @sign_4xi65(<4 x i65> %a) {
242 ; CHECK-LABEL: sign_4xi65:
243 ; CHECK:       // %bb.0:
244 ; CHECK-NEXT:    sbfx x8, x5, #0, #1
245 ; CHECK-NEXT:    sbfx x9, x3, #0, #1
246 ; CHECK-NEXT:    sbfx x10, x1, #0, #1
247 ; CHECK-NEXT:    sbfx x11, x7, #0, #1
248 ; CHECK-NEXT:    lsr x1, x10, #63
249 ; CHECK-NEXT:    lsr x3, x9, #63
250 ; CHECK-NEXT:    lsr x5, x8, #63
251 ; CHECK-NEXT:    lsr x7, x11, #63
252 ; CHECK-NEXT:    orr x0, x10, #0x1
253 ; CHECK-NEXT:    orr x2, x9, #0x1
254 ; CHECK-NEXT:    orr x4, x8, #0x1
255 ; CHECK-NEXT:    orr x6, x11, #0x1
256 ; CHECK-NEXT:    ret
257   %c = icmp sgt <4 x i65> %a, <i65 -1, i65 -1, i65 -1, i65 -1>
258   %res = select <4 x i1> %c, <4 x i65> <i65 1, i65 1, i65 1, i65 1>, <4 x i65 > <i65 -1, i65 -1, i65 -1, i65 -1>
259   ret <4 x i65> %res
262 define i32 @or_neg(i32 %x, i32 %y) {
263 ; CHECK-LABEL: or_neg:
264 ; CHECK:       // %bb.0:
265 ; CHECK-NEXT:    orr w8, w0, #0x1
266 ; CHECK-NEXT:    cmn w1, w8
267 ; CHECK-NEXT:    cset w0, lt
268 ; CHECK-NEXT:    ret
269   %3 = or i32 %x, 1
270   %4 = sub i32 0, %3
271   %5 = icmp sgt i32 %4, %y
272   %6 = zext i1 %5 to i32
273   ret i32 %6
276 define i32 @or_neg_ugt(i32 %x, i32 %y) {
277 ; CHECK-LABEL: or_neg_ugt:
278 ; CHECK:       // %bb.0:
279 ; CHECK-NEXT:    orr w8, w0, #0x1
280 ; CHECK-NEXT:    cmn w1, w8
281 ; CHECK-NEXT:    cset w0, lo
282 ; CHECK-NEXT:    ret
283   %3 = or i32 %x, 1
284   %4 = sub i32 0, %3
285   %5 = icmp ugt i32 %4, %y
286   %6 = zext i1 %5 to i32
287   ret i32 %6
290 ; Negative test
292 define i32 @or_neg_no_smin(i32 %x, i32 %y) {
293 ; CHECK-LABEL: or_neg_no_smin:
294 ; CHECK:       // %bb.0:
295 ; CHECK-NEXT:    neg w8, w0
296 ; CHECK-NEXT:    cmp w8, w1
297 ; CHECK-NEXT:    cset w0, gt
298 ; CHECK-NEXT:    ret
299   %4 = sub i32 0, %x
300   %5 = icmp sgt i32 %4, %y
301   %6 = zext i1 %5 to i32
302   ret i32 %6
305 ; Negative test
307 define i32 @or_neg_ult_no_zero(i32 %x, i32 %y) {
308 ; CHECK-LABEL: or_neg_ult_no_zero:
309 ; CHECK:       // %bb.0:
310 ; CHECK-NEXT:    neg w8, w0
311 ; CHECK-NEXT:    cmp w8, w1
312 ; CHECK-NEXT:    cset w0, lo
313 ; CHECK-NEXT:    ret
314   %4 = sub i32 0, %x
315   %5 = icmp ult i32 %4, %y
316   %6 = zext i1 %5 to i32
317   ret i32 %6
320 define i32 @or_neg_no_smin_but_zero(i32 %x, i32 %y) {
321 ; CHECK-LABEL: or_neg_no_smin_but_zero:
322 ; CHECK:       // %bb.0:
323 ; CHECK-NEXT:    bic w8, w0, w0, asr #31
324 ; CHECK-NEXT:    cmn w1, w8
325 ; CHECK-NEXT:    cset w0, lt
326 ; CHECK-NEXT:    ret
327   %3 = call i32 @llvm.smax.i32(i32 %x, i32 0)
328   %4 = sub i32 0, %3
329   %5 = icmp sgt i32 %4, %y
330   %6 = zext i1 %5 to i32
331   ret i32 %6
334 define i32 @or_neg_slt_zero_but_no_smin(i32 %x, i32 %y) {
335 ; CHECK-LABEL: or_neg_slt_zero_but_no_smin:
336 ; CHECK:       // %bb.0:
337 ; CHECK-NEXT:    mov w8, #9 // =0x9
338 ; CHECK-NEXT:    cmp w0, #9
339 ; CHECK-NEXT:    csel w8, w0, w8, lo
340 ; CHECK-NEXT:    neg w8, w8
341 ; CHECK-NEXT:    cmp w8, w1
342 ; CHECK-NEXT:    cset w0, hi
343 ; CHECK-NEXT:    ret
344   %3 = call i32 @llvm.umin.i32(i32 %x, i32 9)
345   %4 = sub i32 0, %3
346   %5 = icmp ugt i32 %4, %y
347   %6 = zext i1 %5 to i32
348   ret i32 %6
351 define i32 @or_neg2(i32 %x, i32 %y) {
352 ; CHECK-LABEL: or_neg2:
353 ; CHECK:       // %bb.0:
354 ; CHECK-NEXT:    orr w8, w0, #0x1
355 ; CHECK-NEXT:    cmn w1, w8
356 ; CHECK-NEXT:    cset w0, le
357 ; CHECK-NEXT:    ret
358   %3 = or i32 %x, 1
359   %4 = sub i32 0, %3
360   %5 = icmp sge i32 %4, %y
361   %6 = zext i1 %5 to i32
362   ret i32 %6
365 define i32 @or_neg3(i32 %x, i32 %y) {
366 ; CHECK-LABEL: or_neg3:
367 ; CHECK:       // %bb.0:
368 ; CHECK-NEXT:    orr w8, w0, #0x1
369 ; CHECK-NEXT:    cmn w1, w8
370 ; CHECK-NEXT:    cset w0, gt
371 ; CHECK-NEXT:    ret
372   %3 = or i32 %x, 1
373   %4 = sub i32 0, %3
374   %5 = icmp slt i32 %4, %y
375   %6 = zext i1 %5 to i32
376   ret i32 %6
379 define i32 @or_neg4(i32 %x, i32 %y) {
380 ; CHECK-LABEL: or_neg4:
381 ; CHECK:       // %bb.0:
382 ; CHECK-NEXT:    orr w8, w0, #0x1
383 ; CHECK-NEXT:    cmn w1, w8
384 ; CHECK-NEXT:    cset w0, ge
385 ; CHECK-NEXT:    ret
386   %3 = or i32 %x, 1
387   %4 = sub i32 0, %3
388   %5 = icmp sle i32 %4, %y
389   %6 = zext i1 %5 to i32
390   ret i32 %6
393 define i32 @or_neg_ult(i32 %x, i32 %y) {
394 ; CHECK-LABEL: or_neg_ult:
395 ; CHECK:       // %bb.0:
396 ; CHECK-NEXT:    orr w8, w0, #0x1
397 ; CHECK-NEXT:    cmn w1, w8
398 ; CHECK-NEXT:    cset w0, lo
399 ; CHECK-NEXT:    ret
400   %3 = or i32 %x, 1
401   %4 = sub i32 0, %3
402   %5 = icmp ugt i32 %4, %y
403   %6 = zext i1 %5 to i32
404   ret i32 %6
407 define i32 @or_neg_no_smin2(i32 %x, i32 %y) {
408 ; CHECK-LABEL: or_neg_no_smin2:
409 ; CHECK:       // %bb.0:
410 ; CHECK-NEXT:    neg w8, w0
411 ; CHECK-NEXT:    cmp w8, w1
412 ; CHECK-NEXT:    cset w0, ge
413 ; CHECK-NEXT:    ret
414   %4 = sub i32 0, %x
415   %5 = icmp sge i32 %4, %y
416   %6 = zext i1 %5 to i32
417   ret i32 %6
420 ; Negative test
422 define i32 @or_neg_ult_no_zero2(i32 %x, i32 %y) {
423 ; CHECK-LABEL: or_neg_ult_no_zero2:
424 ; CHECK:       // %bb.0:
425 ; CHECK-NEXT:    neg w8, w0
426 ; CHECK-NEXT:    cmp w8, w1
427 ; CHECK-NEXT:    cset w0, lo
428 ; CHECK-NEXT:    ret
429   %4 = sub i32 0, %x
430   %5 = icmp ult i32 %4, %y
431   %6 = zext i1 %5 to i32
432   ret i32 %6
435 define i32 @or_neg_no_smin_but_zero2(i32 %x, i32 %y) {
436 ; CHECK-LABEL: or_neg_no_smin_but_zero2:
437 ; CHECK:       // %bb.0:
438 ; CHECK-NEXT:    bic w8, w0, w0, asr #31
439 ; CHECK-NEXT:    cmn w1, w8
440 ; CHECK-NEXT:    cset w0, ge
441 ; CHECK-NEXT:    ret
442   %3 = call i32 @llvm.smax.i32(i32 %x, i32 0)
443   %4 = sub i32 0, %3
444   %5 = icmp sle i32 %4, %y
445   %6 = zext i1 %5 to i32
446   ret i32 %6
449 define i32 @or_neg_slt_zero_but_no_smin2(i32 %x, i32 %y) {
450 ; CHECK-LABEL: or_neg_slt_zero_but_no_smin2:
451 ; CHECK:       // %bb.0:
452 ; CHECK-NEXT:    mov w8, #9 // =0x9
453 ; CHECK-NEXT:    cmp w0, #9
454 ; CHECK-NEXT:    csel w8, w0, w8, lo
455 ; CHECK-NEXT:    neg w8, w8
456 ; CHECK-NEXT:    cmp w8, w1
457 ; CHECK-NEXT:    cset w0, hs
458 ; CHECK-NEXT:    ret
459   %3 = call i32 @llvm.umin.i32(i32 %x, i32 9)
460   %4 = sub i32 0, %3
461   %5 = icmp uge i32 %4, %y
462   %6 = zext i1 %5 to i32
463   ret i32 %6
466 declare i32 @llvm.smax.i32(i32, i32)
467 declare i32 @llvm.umax.i32(i32, i32)
468 declare void @use_4xi1(<4 x i1>)