xref: /llvm-project/llvm/test/CodeGen/AArch64/arm64-csel.ll (revision d04ae1b15ff3064e9fb43a3a15f43285d4ee7998)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -debugify-and-strip-all-safe -O3 < %s | FileCheck %s
3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32:64"
4target triple = "arm64-unknown-unknown"
5
6define i32 @foo1(i32 %b, i32 %c) nounwind readnone ssp {
7; CHECK-LABEL: foo1:
8; CHECK:       // %bb.0: // %entry
9; CHECK-NEXT:    cmp w1, #0
10; CHECK-NEXT:    add w8, w1, w0
11; CHECK-NEXT:    cinc w0, w8, ne
12; CHECK-NEXT:    ret
13entry:
14  %not.tobool = icmp ne i32 %c, 0
15  %add = zext i1 %not.tobool to i32
16  %b.add = add i32 %c, %b
17  %add1 = add i32 %b.add, %add
18  ret i32 %add1
19}
20
21define i32 @foo2(i32 %b, i32 %c) nounwind readnone ssp {
22; CHECK-LABEL: foo2:
23; CHECK:       // %bb.0: // %entry
24; CHECK-NEXT:    cmp w1, #0
25; CHECK-NEXT:    cneg w8, w0, ne
26; CHECK-NEXT:    add w0, w8, w1
27; CHECK-NEXT:    ret
28entry:
29  %mul = sub i32 0, %b
30  %tobool = icmp eq i32 %c, 0
31  %b.mul = select i1 %tobool, i32 %b, i32 %mul
32  %add = add nsw i32 %b.mul, %c
33  ret i32 %add
34}
35
36define i32 @foo3(i32 %b, i32 %c) nounwind readnone ssp {
37; CHECK-LABEL: foo3:
38; CHECK:       // %bb.0: // %entry
39; CHECK-NEXT:    cmp w1, #0
40; CHECK-NEXT:    cinv w8, w0, ne
41; CHECK-NEXT:    add w0, w8, w1
42; CHECK-NEXT:    ret
43entry:
44  %not.tobool = icmp ne i32 %c, 0
45  %xor = sext i1 %not.tobool to i32
46  %b.xor = xor i32 %xor, %b
47  %add = add nsw i32 %b.xor, %c
48  ret i32 %add
49}
50
51; rdar://11632325
52define i32@foo4(i32 %a) nounwind ssp {
53; CHECK-LABEL: foo4:
54; CHECK:       // %bb.0:
55; CHECK-NEXT:    cmp w0, #0
56; CHECK-NEXT:    cneg w0, w0, mi
57; CHECK-NEXT:    ret
58  %cmp = icmp sgt i32 %a, -1
59  %neg = sub nsw i32 0, %a
60  %cond = select i1 %cmp, i32 %a, i32 %neg
61  ret i32 %cond
62}
63
64define i32@foo5(i32 %a, i32 %b) nounwind ssp {
65; CHECK-LABEL: foo5:
66; CHECK:       // %bb.0: // %entry
67; CHECK-NEXT:    subs w8, w0, w1
68; CHECK-NEXT:    cneg w0, w8, mi
69; CHECK-NEXT:    ret
70entry:
71  %sub = sub nsw i32 %a, %b
72  %cmp = icmp sgt i32 %sub, -1
73  %sub3 = sub nsw i32 0, %sub
74  %cond = select i1 %cmp, i32 %sub, i32 %sub3
75  ret i32 %cond
76}
77
78; make sure we can handle branch instruction in optimizeCompare.
79define i32@foo6(i32 %a, i32 %b) nounwind ssp {
80; CHECK-LABEL: foo6:
81; CHECK:       // %bb.0: // %common.ret
82; CHECK-NEXT:    subs w8, w0, w1
83; CHECK-NEXT:    csinc w0, w8, wzr, le
84; CHECK-NEXT:    ret
85  %sub = sub nsw i32 %a, %b
86  %cmp = icmp sgt i32 %sub, 0
87  br i1 %cmp, label %l.if, label %l.else
88
89l.if:
90  ret i32 1
91
92l.else:
93  ret i32 %sub
94}
95
96; If CPSR is used multiple times and V flag is used, we don't remove cmp.
97define i32 @foo7(i32 %a, i32 %b) nounwind {
98; CHECK-LABEL: foo7:
99; CHECK:       // %bb.0: // %entry
100; CHECK-NEXT:    subs w8, w0, w1
101; CHECK-NEXT:    cneg w9, w8, mi
102; CHECK-NEXT:    cmn w8, #1
103; CHECK-NEXT:    csel w10, w9, w0, lt
104; CHECK-NEXT:    cmp w8, #0
105; CHECK-NEXT:    csel w0, w10, w9, ge
106; CHECK-NEXT:    ret
107entry:
108  %sub = sub nsw i32 %a, %b
109  %cmp = icmp sgt i32 %sub, -1
110  %sub3 = sub nsw i32 0, %sub
111  %cond = select i1 %cmp, i32 %sub, i32 %sub3
112  br i1 %cmp, label %if.then, label %if.else
113
114if.then:
115  %cmp2 = icmp slt i32 %sub, -1
116  %sel = select i1 %cmp2, i32 %cond, i32 %a
117  ret i32 %sel
118
119if.else:
120  ret i32 %cond
121}
122
123define i32 @foo8(i32 %v, i32 %a, i32 %b) nounwind readnone ssp {
124; CHECK-LABEL: foo8:
125; CHECK:       // %bb.0: // %entry
126; CHECK-NEXT:    cmp w0, #0
127; CHECK-NEXT:    csinv w0, w1, w2, ne
128; CHECK-NEXT:    ret
129entry:
130  %tobool = icmp eq i32 %v, 0
131  %neg = xor i32 -1, %b
132  %cond = select i1 %tobool, i32 %neg, i32 %a
133  ret i32 %cond
134}
135
136define i32 @foo9(i32 %v) nounwind readnone optsize ssp {
137; CHECK-LABEL: foo9:
138; CHECK:       // %bb.0: // %entry
139; CHECK-NEXT:    mov w8, #4 // =0x4
140; CHECK-NEXT:    cmp w0, #0
141; CHECK-NEXT:    cinv w0, w8, eq
142; CHECK-NEXT:    ret
143entry:
144  %tobool = icmp ne i32 %v, 0
145  %cond = select i1 %tobool, i32 4, i32 -5
146  ret i32 %cond
147}
148
149define i64 @foo10(i64 %v) nounwind readnone optsize ssp {
150; CHECK-LABEL: foo10:
151; CHECK:       // %bb.0: // %entry
152; CHECK-NEXT:    mov w8, #4 // =0x4
153; CHECK-NEXT:    cmp x0, #0
154; CHECK-NEXT:    cinv x0, x8, eq
155; CHECK-NEXT:    ret
156entry:
157  %tobool = icmp ne i64 %v, 0
158  %cond = select i1 %tobool, i64 4, i64 -5
159  ret i64 %cond
160}
161
162define i32 @foo11(i32 %v) nounwind readnone optsize ssp {
163; CHECK-LABEL: foo11:
164; CHECK:       // %bb.0: // %entry
165; CHECK-NEXT:    mov w8, #4 // =0x4
166; CHECK-NEXT:    cmp w0, #0
167; CHECK-NEXT:    cneg w0, w8, eq
168; CHECK-NEXT:    ret
169entry:
170  %tobool = icmp ne i32 %v, 0
171  %cond = select i1 %tobool, i32 4, i32 -4
172  ret i32 %cond
173}
174
175define i64 @foo12(i64 %v) nounwind readnone optsize ssp {
176; CHECK-LABEL: foo12:
177; CHECK:       // %bb.0: // %entry
178; CHECK-NEXT:    mov w8, #4 // =0x4
179; CHECK-NEXT:    cmp x0, #0
180; CHECK-NEXT:    cneg x0, x8, eq
181; CHECK-NEXT:    ret
182entry:
183  %tobool = icmp ne i64 %v, 0
184  %cond = select i1 %tobool, i64 4, i64 -4
185  ret i64 %cond
186}
187
188define i32 @foo13(i32 %v, i32 %a, i32 %b) nounwind readnone optsize ssp {
189; CHECK-LABEL: foo13:
190; CHECK:       // %bb.0: // %entry
191; CHECK-NEXT:    cmp w0, #0
192; CHECK-NEXT:    csneg w0, w1, w2, ne
193; CHECK-NEXT:    ret
194entry:
195  %tobool = icmp eq i32 %v, 0
196  %sub = sub i32 0, %b
197  %cond = select i1 %tobool, i32 %sub, i32 %a
198  ret i32 %cond
199}
200
201define i64 @foo14(i64 %v, i64 %a, i64 %b) nounwind readnone optsize ssp {
202; CHECK-LABEL: foo14:
203; CHECK:       // %bb.0: // %entry
204; CHECK-NEXT:    cmp x0, #0
205; CHECK-NEXT:    csneg x0, x1, x2, ne
206; CHECK-NEXT:    ret
207entry:
208  %tobool = icmp eq i64 %v, 0
209  %sub = sub i64 0, %b
210  %cond = select i1 %tobool, i64 %sub, i64 %a
211  ret i64 %cond
212}
213
214define i32 @foo15(i32 %a, i32 %b) nounwind readnone optsize ssp {
215; CHECK-LABEL: foo15:
216; CHECK:       // %bb.0: // %entry
217; CHECK-NEXT:    mov w8, #1 // =0x1
218; CHECK-NEXT:    cmp w0, w1
219; CHECK-NEXT:    cinc w0, w8, gt
220; CHECK-NEXT:    ret
221entry:
222  %cmp = icmp sgt i32 %a, %b
223  %. = select i1 %cmp, i32 2, i32 1
224  ret i32 %.
225}
226
227define i32 @foo16(i32 %a, i32 %b) nounwind readnone optsize ssp {
228; CHECK-LABEL: foo16:
229; CHECK:       // %bb.0: // %entry
230; CHECK-NEXT:    mov w8, #1 // =0x1
231; CHECK-NEXT:    cmp w0, w1
232; CHECK-NEXT:    cinc w0, w8, le
233; CHECK-NEXT:    ret
234entry:
235  %cmp = icmp sgt i32 %a, %b
236  %. = select i1 %cmp, i32 1, i32 2
237  ret i32 %.
238}
239
240define i64 @foo17(i64 %a, i64 %b) nounwind readnone optsize ssp {
241; CHECK-LABEL: foo17:
242; CHECK:       // %bb.0: // %entry
243; CHECK-NEXT:    mov w8, #1 // =0x1
244; CHECK-NEXT:    cmp x0, x1
245; CHECK-NEXT:    cinc x0, x8, gt
246; CHECK-NEXT:    ret
247entry:
248  %cmp = icmp sgt i64 %a, %b
249  %. = select i1 %cmp, i64 2, i64 1
250  ret i64 %.
251}
252
253define i64 @foo18(i64 %a, i64 %b) nounwind readnone optsize ssp {
254; CHECK-LABEL: foo18:
255; CHECK:       // %bb.0: // %entry
256; CHECK-NEXT:    mov w8, #1 // =0x1
257; CHECK-NEXT:    cmp x0, x1
258; CHECK-NEXT:    cinc x0, x8, le
259; CHECK-NEXT:    ret
260entry:
261  %cmp = icmp sgt i64 %a, %b
262  %. = select i1 %cmp, i64 1, i64 2
263  ret i64 %.
264}
265
266; Regression test for TrueVal + 1 overflow
267define i64 @foo18_overflow1(i64 %a, i64 %b) nounwind readnone optsize ssp {
268; CHECK-LABEL: foo18_overflow1:
269; CHECK:       // %bb.0: // %entry
270; CHECK-NEXT:    mov x8, #9223372036854775807 // =0x7fffffffffffffff
271; CHECK-NEXT:    cmp x0, x1
272; CHECK-NEXT:    csel x0, x8, xzr, gt
273; CHECK-NEXT:    ret
274entry:
275  %cmp = icmp sgt i64 %a, %b
276  %. = select i1 %cmp, i64 9223372036854775807, i64 0
277  ret i64 %.
278}
279
280; Regression test for FalseVal + 1 overflow
281define i64 @foo18_overflow2(i64 %a, i64 %b) nounwind readnone optsize ssp {
282; CHECK-LABEL: foo18_overflow2:
283; CHECK:       // %bb.0: // %entry
284; CHECK-NEXT:    mov x8, #9223372036854775807 // =0x7fffffffffffffff
285; CHECK-NEXT:    cmp x0, x1
286; CHECK-NEXT:    csel x0, xzr, x8, gt
287; CHECK-NEXT:    ret
288entry:
289  %cmp = icmp sgt i64 %a, %b
290  %. = select i1 %cmp, i64 0, i64 9223372036854775807
291  ret i64 %.
292}
293
294; Regression test for FalseVal - TrueVal overflow
295define i64 @foo18_overflow3(i1 %cmp) nounwind readnone optsize ssp {
296; CHECK-LABEL: foo18_overflow3:
297; CHECK:       // %bb.0: // %entry
298; CHECK-NEXT:    mov x8, #-9223372036854775808 // =0x8000000000000000
299; CHECK-NEXT:    tst w0, #0x1
300; CHECK-NEXT:    csel x0, x8, xzr, ne
301; CHECK-NEXT:    ret
302entry:
303  %. = select i1 %cmp, i64 -9223372036854775808, i64 0
304  ret i64 %.
305}
306
307; Regression test for TrueVal - FalseVal overflow
308define i64 @foo18_overflow4(i1 %cmp) nounwind readnone optsize ssp {
309; CHECK-LABEL: foo18_overflow4:
310; CHECK:       // %bb.0: // %entry
311; CHECK-NEXT:    mov x8, #-9223372036854775808 // =0x8000000000000000
312; CHECK-NEXT:    tst w0, #0x1
313; CHECK-NEXT:    csel x0, xzr, x8, ne
314; CHECK-NEXT:    ret
315entry:
316  %. = select i1 %cmp, i64 0, i64 -9223372036854775808
317  ret i64 %.
318}
319
320define i64 @foo19(i64 %a, i64 %b, i64 %c) {
321; CHECK-LABEL: foo19:
322; CHECK:       // %bb.0: // %entry
323; CHECK-NEXT:    cmp x0, x1
324; CHECK-NEXT:    cinc x0, x2, lo
325; CHECK-NEXT:    ret
326entry:
327  %cmp = icmp ult i64 %a, %b
328  %inc = zext i1 %cmp to i64
329  %inc.c = add i64 %inc, %c
330  ret i64 %inc.c
331}
332
333define i32 @foo20(i32 %x) {
334; CHECK-LABEL: foo20:
335; CHECK:       // %bb.0:
336; CHECK-NEXT:    mov w8, #6 // =0x6
337; CHECK-NEXT:    cmp w0, #5
338; CHECK-NEXT:    csinc w0, w8, wzr, eq
339; CHECK-NEXT:    ret
340  %cmp = icmp eq i32 %x, 5
341  %res = select i1 %cmp, i32 6, i32 1
342  ret i32 %res
343}
344
345define i64 @foo21(i64 %x) {
346; CHECK-LABEL: foo21:
347; CHECK:       // %bb.0:
348; CHECK-NEXT:    mov w8, #6 // =0x6
349; CHECK-NEXT:    cmp x0, #5
350; CHECK-NEXT:    csinc x0, x8, xzr, eq
351; CHECK-NEXT:    ret
352  %cmp = icmp eq i64 %x, 5
353  %res = select i1 %cmp, i64 6, i64 1
354  ret i64 %res
355}
356
357define i32 @foo22(i32 %x) {
358; CHECK-LABEL: foo22:
359; CHECK:       // %bb.0:
360; CHECK-NEXT:    mov w8, #6 // =0x6
361; CHECK-NEXT:    cmp w0, #5
362; CHECK-NEXT:    csinc w0, w8, wzr, ne
363; CHECK-NEXT:    ret
364  %cmp = icmp eq i32 %x, 5
365  %res = select i1 %cmp, i32 1, i32 6
366  ret i32 %res
367}
368
369define i64 @foo23(i64 %x) {
370; CHECK-LABEL: foo23:
371; CHECK:       // %bb.0:
372; CHECK-NEXT:    mov w8, #6 // =0x6
373; CHECK-NEXT:    cmp x0, #5
374; CHECK-NEXT:    csinc x0, x8, xzr, ne
375; CHECK-NEXT:    ret
376  %cmp = icmp eq i64 %x, 5
377  %res = select i1 %cmp, i64 1, i64 6
378  ret i64 %res
379}
380
381define i16 @foo24(ptr nocapture readonly %A, ptr nocapture readonly %B) {
382; CHECK-LABEL: foo24:
383; CHECK:       // %bb.0: // %entry
384; CHECK-NEXT:    ldrb w8, [x0]
385; CHECK-NEXT:    ldrb w9, [x1]
386; CHECK-NEXT:    cmp w8, #3
387; CHECK-NEXT:    cset w8, hi
388; CHECK-NEXT:    cmp w9, #33
389; CHECK-NEXT:    cinc w0, w8, hi
390; CHECK-NEXT:    ret
391entry:
392  %0 = load i8, ptr %A, align 1
393  %cmp = icmp ugt i8 %0, 3
394  %conv1 = zext i1 %cmp to i16
395  %1 = load i8, ptr %B, align 1
396  %cmp4 = icmp ugt i8 %1, 33
397  %conv5 = zext i1 %cmp4 to i16
398  %add = add nuw nsw i16 %conv5, %conv1
399  ret i16 %add
400}
401
402define i64 @foo25(ptr nocapture readonly %A, ptr nocapture readonly %B) {
403; CHECK-LABEL: foo25:
404; CHECK:       // %bb.0: // %entry
405; CHECK-NEXT:    ldr x8, [x1]
406; CHECK-NEXT:    ldr x9, [x0]
407; CHECK-NEXT:    cmp x8, #33
408; CHECK-NEXT:    cset w8, hi
409; CHECK-NEXT:    cmp x9, #3
410; CHECK-NEXT:    cinc x0, x8, hi
411; CHECK-NEXT:    ret
412entry:
413  %0 = load i64, ptr %A, align 1
414  %cmp = icmp ugt i64 %0, 3
415  %conv1 = zext i1 %cmp to i64
416  %1 = load i64, ptr %B, align 1
417  %cmp4 = icmp ugt i64 %1, 33
418  %conv5 = zext i1 %cmp4 to i64
419  %add = add nuw nsw i64 %conv5, %conv1
420  ret i64 %add
421}
422
423define i32 @or(i32 %num, i32 %x) {
424; CHECK-LABEL: or:
425; CHECK:       // %bb.0: // %entry
426; CHECK-NEXT:    and w8, w0, #0xff00
427; CHECK-NEXT:    cmp w1, #0
428; CHECK-NEXT:    cinc w0, w8, ne
429; CHECK-NEXT:    ret
430entry:
431  %and = and i32 %num, 65280
432  %tobool.not = icmp ne i32 %x, 0
433  %cond = zext i1 %tobool.not to i32
434  %or = or disjoint i32 %and, %cond
435  ret i32 %or
436}
437
438define i64 @or64(i64 %num, i64 %x) {
439; CHECK-LABEL: or64:
440; CHECK:       // %bb.0: // %entry
441; CHECK-NEXT:    and x8, x0, #0xff00
442; CHECK-NEXT:    cmp x1, #0
443; CHECK-NEXT:    cinc x0, x8, ne
444; CHECK-NEXT:    ret
445entry:
446  %and = and i64 %num, 65280
447  %tobool.not = icmp ne i64 %x, 0
448  %conv = zext i1 %tobool.not to i64
449  %or = or disjoint i64 %and, %conv
450  ret i64 %or
451}
452
453define i32 @selor32(i32 %num, i32 %x) {
454; CHECK-LABEL: selor32:
455; CHECK:       // %bb.0: // %entry
456; CHECK-NEXT:    and w8, w0, #0xff00
457; CHECK-NEXT:    cmp w1, #0
458; CHECK-NEXT:    cinc w0, w8, ne
459; CHECK-NEXT:    ret
460entry:
461  %and = and i32 %num, 65280
462  %tobool.not = icmp ne i32 %x, 0
463  %or = or disjoint i32 %and, 1
464  %sel = select i1 %tobool.not, i32 %or, i32 %and
465  ret i32 %sel
466}
467
468define i32 @selor32_2(i32 %num, i32 %x) {
469; CHECK-LABEL: selor32_2:
470; CHECK:       // %bb.0: // %entry
471; CHECK-NEXT:    and w8, w0, #0xff00
472; CHECK-NEXT:    cmp w1, #0
473; CHECK-NEXT:    orr w9, w8, #0x2
474; CHECK-NEXT:    csel w0, w9, w8, ne
475; CHECK-NEXT:    ret
476entry:
477  %and = and i32 %num, 65280
478  %tobool.not = icmp ne i32 %x, 0
479  %or = or disjoint i32 %and, 2
480  %sel = select i1 %tobool.not, i32 %or, i32 %and
481  ret i32 %sel
482}
483
484define i64 @selor64(i64 %num, i64 %x) {
485; CHECK-LABEL: selor64:
486; CHECK:       // %bb.0: // %entry
487; CHECK-NEXT:    and x8, x0, #0xff00
488; CHECK-NEXT:    cmp x1, #0
489; CHECK-NEXT:    cinc x0, x8, ne
490; CHECK-NEXT:    ret
491entry:
492  %and = and i64 %num, 65280
493  %tobool.not = icmp ne i64 %x, 0
494  %or = or disjoint i64 %and, 1
495  %sel = select i1 %tobool.not, i64 %or, i64 %and
496  ret i64 %sel
497}
498
499; Same as above with disjoint but without knowing haveNoCommonBitsSet.
500define i64 @selor64_disjoint(i64 %num, i64 %x) {
501; CHECK-LABEL: selor64_disjoint:
502; CHECK:       // %bb.0: // %entry
503; CHECK-NEXT:    cmp x1, #0
504; CHECK-NEXT:    cinc x0, x0, ne
505; CHECK-NEXT:    ret
506entry:
507  %tobool.not = icmp ne i64 %x, 0
508  %or = or disjoint i64 %num, 1
509  %sel = select i1 %tobool.not, i64 %or, i64 %num
510  ret i64 %sel
511}
512