xref: /llvm-project/llvm/test/CodeGen/AArch64/cmp-select-sign.ll (revision b42fe6740ec696dca0e3dc914d2638088caa3f53)
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
3
4define 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
13}
14
15define 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
24}
25
26define 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
35}
36
37define 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
46}
47
48define 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
57}
58
59define 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
68}
69
70
71define 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
81}
82
83define 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
91}
92
93define 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
102}
103
104define 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
112}
113
114define <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
124}
125
126define <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
136}
137
138define <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
148}
149
150define <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
159}
160
161define <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
170}
171
172define <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
193}
194
195; Second icmp operand breaks sign pattern.
196define <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
209}
210
211; First select operand breaks sign pattern.
212define <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
223}
224
225; Second select operand breaks sign pattern.
226define <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
238}
239
240; i65 is not legal.
241define <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
260}
261
262define 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
274}
275
276define 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
288}
289
290; Negative test
291
292define 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
303}
304
305; Negative test
306
307define 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
318}
319
320define 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
332}
333
334define 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
349}
350
351define 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
363}
364
365define 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
377}
378
379define 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
391}
392
393define 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
405}
406
407define 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
418}
419
420; Negative test
421
422define 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
433}
434
435define 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
447}
448
449define 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
464}
465
466declare i32 @llvm.smax.i32(i32, i32)
467declare i32 @llvm.umax.i32(i32, i32)
468declare void @use_4xi1(<4 x i1>)
469