xref: /llvm-project/llvm/test/CodeGen/AArch64/arm64-ccmp.ll (revision 5c348f692a8dff98a3780d0b859fb0949eccbaca)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -debugify-and-strip-all-safe -mcpu=cyclone -verify-machineinstrs -aarch64-enable-ccmp -aarch64-stress-ccmp | FileCheck %s --check-prefixes=CHECK,SDISEL
3; RUN: llc < %s -debugify-and-strip-all-safe -mcpu=cyclone -verify-machineinstrs -aarch64-enable-ccmp -aarch64-stress-ccmp -global-isel | FileCheck %s --check-prefixes=CHECK,GISEL
4target triple = "arm64-apple-ios"
5
6define i32 @single_same(i32 %a, i32 %b) nounwind ssp {
7; CHECK-LABEL: single_same:
8; CHECK:       ; %bb.0: ; %entry
9; CHECK-NEXT:    cmp w0, #5
10; CHECK-NEXT:    ccmp w1, #17, #4, ne
11; CHECK-NEXT:    b.ne LBB0_2
12; CHECK-NEXT:  ; %bb.1: ; %if.then
13; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
14; CHECK-NEXT:    bl _foo
15; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
16; CHECK-NEXT:  LBB0_2: ; %if.end
17; CHECK-NEXT:    mov w0, #7 ; =0x7
18; CHECK-NEXT:    ret
19entry:
20  %cmp = icmp eq i32 %a, 5
21  %cmp1 = icmp eq i32 %b, 17
22  %or.cond = or i1 %cmp, %cmp1
23  br i1 %or.cond, label %if.then, label %if.end
24
25if.then:
26  %call = tail call i32 @foo() nounwind
27  br label %if.end
28
29if.end:
30  ret i32 7
31}
32
33; Different condition codes for the two compares.
34define i32 @single_different(i32 %a, i32 %b) nounwind ssp {
35; SDISEL-LABEL: single_different:
36; SDISEL:       ; %bb.0: ; %entry
37; SDISEL-NEXT:    cmp w0, #6
38; SDISEL-NEXT:    ccmp w1, #17, #0, ge
39; SDISEL-NEXT:    b.eq LBB1_2
40; SDISEL-NEXT:  ; %bb.1: ; %if.then
41; SDISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
42; SDISEL-NEXT:    bl _foo
43; SDISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
44; SDISEL-NEXT:  LBB1_2: ; %if.end
45; SDISEL-NEXT:    mov w0, #7 ; =0x7
46; SDISEL-NEXT:    ret
47;
48; GISEL-LABEL: single_different:
49; GISEL:       ; %bb.0: ; %entry
50; GISEL-NEXT:    cmp w0, #5
51; GISEL-NEXT:    ccmp w1, #17, #0, gt
52; GISEL-NEXT:    b.eq LBB1_2
53; GISEL-NEXT:  ; %bb.1: ; %if.then
54; GISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
55; GISEL-NEXT:    bl _foo
56; GISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
57; GISEL-NEXT:  LBB1_2: ; %if.end
58; GISEL-NEXT:    mov w0, #7 ; =0x7
59; GISEL-NEXT:    ret
60entry:
61  %cmp = icmp sle i32 %a, 5
62  %cmp1 = icmp ne i32 %b, 17
63  %or.cond = or i1 %cmp, %cmp1
64  br i1 %or.cond, label %if.then, label %if.end
65
66if.then:
67  %call = tail call i32 @foo() nounwind
68  br label %if.end
69
70if.end:
71  ret i32 7
72}
73
74; Second block clobbers the flags, can't convert (easily).
75define i32 @single_flagclobber(i32 %a, i32 %b) nounwind ssp {
76; SDISEL-LABEL: single_flagclobber:
77; SDISEL:       ; %bb.0: ; %entry
78; SDISEL-NEXT:    cmp w0, #5
79; SDISEL-NEXT:    b.eq LBB2_2
80; SDISEL-NEXT:  ; %bb.1: ; %lor.lhs.false
81; SDISEL-NEXT:    lsl w8, w1, #1
82; SDISEL-NEXT:    cmp w1, #7
83; SDISEL-NEXT:    csinc w8, w8, w1, lt
84; SDISEL-NEXT:    cmp w8, #16
85; SDISEL-NEXT:    b.gt LBB2_3
86; SDISEL-NEXT:  LBB2_2: ; %if.then
87; SDISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
88; SDISEL-NEXT:    bl _foo
89; SDISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
90; SDISEL-NEXT:  LBB2_3: ; %if.end
91; SDISEL-NEXT:    mov w0, #7 ; =0x7
92; SDISEL-NEXT:    ret
93;
94; GISEL-LABEL: single_flagclobber:
95; GISEL:       ; %bb.0: ; %entry
96; GISEL-NEXT:    cmp w0, #5
97; GISEL-NEXT:    b.eq LBB2_2
98; GISEL-NEXT:  ; %bb.1: ; %lor.lhs.false
99; GISEL-NEXT:    lsl w8, w1, #1
100; GISEL-NEXT:    cmp w1, #7
101; GISEL-NEXT:    csinc w8, w8, w1, lt
102; GISEL-NEXT:    cmp w8, #17
103; GISEL-NEXT:    b.ge LBB2_3
104; GISEL-NEXT:  LBB2_2: ; %if.then
105; GISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
106; GISEL-NEXT:    bl _foo
107; GISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
108; GISEL-NEXT:  LBB2_3: ; %if.end
109; GISEL-NEXT:    mov w0, #7 ; =0x7
110; GISEL-NEXT:    ret
111entry:
112  %cmp = icmp eq i32 %a, 5
113  br i1 %cmp, label %if.then, label %lor.lhs.false
114
115lor.lhs.false:                                    ; preds = %entry
116  %cmp1 = icmp slt i32 %b, 7
117  %mul = shl nsw i32 %b, 1
118  %add = add nsw i32 %b, 1
119  %cond = select i1 %cmp1, i32 %mul, i32 %add
120  %cmp2 = icmp slt i32 %cond, 17
121  br i1 %cmp2, label %if.then, label %if.end
122
123if.then:                                          ; preds = %lor.lhs.false, %entry
124  %call = tail call i32 @foo() nounwind
125  br label %if.end
126
127if.end:                                           ; preds = %if.then, %lor.lhs.false
128  ret i32 7
129}
130
131; Second block clobbers the flags and ends with a tbz terminator.
132define i32 @single_flagclobber_tbz(i32 %a, i32 %b) nounwind ssp {
133; CHECK-LABEL: single_flagclobber_tbz:
134; CHECK:       ; %bb.0: ; %entry
135; CHECK-NEXT:    cmp w0, #5
136; CHECK-NEXT:    b.eq LBB3_2
137; CHECK-NEXT:  ; %bb.1: ; %lor.lhs.false
138; CHECK-NEXT:    lsl w8, w1, #1
139; CHECK-NEXT:    cmp w1, #7
140; CHECK-NEXT:    csinc w8, w8, w1, lt
141; CHECK-NEXT:    tbz w8, #3, LBB3_3
142; CHECK-NEXT:  LBB3_2: ; %if.then
143; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
144; CHECK-NEXT:    bl _foo
145; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
146; CHECK-NEXT:  LBB3_3: ; %if.end
147; CHECK-NEXT:    mov w0, #7 ; =0x7
148; CHECK-NEXT:    ret
149entry:
150  %cmp = icmp eq i32 %a, 5
151  br i1 %cmp, label %if.then, label %lor.lhs.false
152
153lor.lhs.false:                                    ; preds = %entry
154  %cmp1 = icmp slt i32 %b, 7
155  %mul = shl nsw i32 %b, 1
156  %add = add nsw i32 %b, 1
157  %cond = select i1 %cmp1, i32 %mul, i32 %add
158  %and = and i32 %cond, 8
159  %cmp2 = icmp ne i32 %and, 0
160  br i1 %cmp2, label %if.then, label %if.end
161
162if.then:                                          ; preds = %lor.lhs.false, %entry
163  %call = tail call i32 @foo() nounwind
164  br label %if.end
165
166if.end:                                           ; preds = %if.then, %lor.lhs.false
167  ret i32 7
168}
169
170; Speculatively execute division by zero.
171; The sdiv/udiv instructions do not trap when the divisor is zero, so they are
172; safe to speculate.
173define i32 @speculate_division(i32 %a, i32 %b) nounwind ssp {
174; SDISEL-LABEL: speculate_division:
175; SDISEL:       ; %bb.0: ; %entry
176; SDISEL-NEXT:    cmp w0, #1
177; SDISEL-NEXT:    sdiv w8, w1, w0
178; SDISEL-NEXT:    ccmp w8, #16, #0, ge
179; SDISEL-NEXT:    b.le LBB4_2
180; SDISEL-NEXT:  ; %bb.1: ; %if.end
181; SDISEL-NEXT:    mov w0, #7 ; =0x7
182; SDISEL-NEXT:    ret
183; SDISEL-NEXT:  LBB4_2: ; %if.then
184; SDISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
185; SDISEL-NEXT:    bl _foo
186; SDISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
187; SDISEL-NEXT:    mov w0, #7 ; =0x7
188; SDISEL-NEXT:    ret
189;
190; GISEL-LABEL: speculate_division:
191; GISEL:       ; %bb.0: ; %entry
192; GISEL-NEXT:    cmp w0, #0
193; GISEL-NEXT:    sdiv w8, w1, w0
194; GISEL-NEXT:    ccmp w8, #17, #0, gt
195; GISEL-NEXT:    b.lt LBB4_2
196; GISEL-NEXT:  ; %bb.1: ; %if.end
197; GISEL-NEXT:    mov w0, #7 ; =0x7
198; GISEL-NEXT:    ret
199; GISEL-NEXT:  LBB4_2: ; %if.then
200; GISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
201; GISEL-NEXT:    bl _foo
202; GISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
203; GISEL-NEXT:    mov w0, #7 ; =0x7
204; GISEL-NEXT:    ret
205entry:
206  %cmp = icmp sgt i32 %a, 0
207  br i1 %cmp, label %land.lhs.true, label %if.end
208
209land.lhs.true:
210  %div = sdiv i32 %b, %a
211  %cmp1 = icmp slt i32 %div, 17
212  br i1 %cmp1, label %if.then, label %if.end
213
214if.then:
215  %call = tail call i32 @foo() nounwind
216  br label %if.end
217
218if.end:
219  ret i32 7
220}
221
222; Floating point compare.
223define i32 @single_fcmp(i32 %a, float %b) nounwind ssp {
224; SDISEL-LABEL: single_fcmp:
225; SDISEL:       ; %bb.0: ; %entry
226; SDISEL-NEXT:    cmp w0, #1
227; SDISEL-NEXT:    scvtf s1, w0
228; SDISEL-NEXT:    fdiv s0, s0, s1
229; SDISEL-NEXT:    fmov s1, #17.00000000
230; SDISEL-NEXT:    fccmp s0, s1, #8, ge
231; SDISEL-NEXT:    b.ge LBB5_2
232; SDISEL-NEXT:  ; %bb.1: ; %if.end
233; SDISEL-NEXT:    mov w0, #7 ; =0x7
234; SDISEL-NEXT:    ret
235; SDISEL-NEXT:  LBB5_2: ; %if.then
236; SDISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
237; SDISEL-NEXT:    bl _foo
238; SDISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
239; SDISEL-NEXT:    mov w0, #7 ; =0x7
240; SDISEL-NEXT:    ret
241;
242; GISEL-LABEL: single_fcmp:
243; GISEL:       ; %bb.0: ; %entry
244; GISEL-NEXT:    cmp w0, #0
245; GISEL-NEXT:    scvtf s1, w0
246; GISEL-NEXT:    fdiv s0, s0, s1
247; GISEL-NEXT:    fmov s1, #17.00000000
248; GISEL-NEXT:    fccmp s0, s1, #8, gt
249; GISEL-NEXT:    b.ge LBB5_2
250; GISEL-NEXT:  ; %bb.1: ; %if.end
251; GISEL-NEXT:    mov w0, #7 ; =0x7
252; GISEL-NEXT:    ret
253; GISEL-NEXT:  LBB5_2: ; %if.then
254; GISEL-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
255; GISEL-NEXT:    bl _foo
256; GISEL-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
257; GISEL-NEXT:    mov w0, #7 ; =0x7
258; GISEL-NEXT:    ret
259entry:
260  %cmp = icmp sgt i32 %a, 0
261  br i1 %cmp, label %land.lhs.true, label %if.end
262
263land.lhs.true:
264  %conv = sitofp i32 %a to float
265  %div = fdiv float %b, %conv
266  %cmp1 = fcmp oge float %div, 1.700000e+01
267  br i1 %cmp1, label %if.then, label %if.end
268
269if.then:
270  %call = tail call i32 @foo() nounwind
271  br label %if.end
272
273if.end:
274  ret i32 7
275}
276
277; Chain multiple compares.
278define void @multi_different(i32 %a, i32 %b, i32 %c) nounwind ssp {
279; CHECK-LABEL: multi_different:
280; CHECK:       ; %bb.0: ; %entry
281; CHECK-NEXT:    cmp w0, w1
282; CHECK-NEXT:    sdiv w8, w1, w0
283; CHECK-NEXT:    ccmp w8, #5, #0, gt
284; CHECK-NEXT:    ccmp w8, w2, #4, eq
285; CHECK-NEXT:    b.gt LBB6_2
286; CHECK-NEXT:  ; %bb.1: ; %if.end
287; CHECK-NEXT:    ret
288; CHECK-NEXT:  LBB6_2: ; %if.then
289; CHECK-NEXT:    b _foo
290entry:
291  %cmp = icmp sgt i32 %a, %b
292  br i1 %cmp, label %land.lhs.true, label %if.end
293
294land.lhs.true:
295  %div = sdiv i32 %b, %a
296  %cmp1 = icmp eq i32 %div, 5
297  %cmp4 = icmp sgt i32 %div, %c
298  %or.cond = and i1 %cmp1, %cmp4
299  br i1 %or.cond, label %if.then, label %if.end
300
301if.then:
302  %call = tail call i32 @foo() nounwind
303  br label %if.end
304
305if.end:
306  ret void
307}
308
309; Convert a cbz in the head block.
310define i32 @cbz_head(i32 %a, i32 %b) nounwind ssp {
311; CHECK-LABEL: cbz_head:
312; CHECK:       ; %bb.0: ; %entry
313; CHECK-NEXT:    cmp w0, #0
314; CHECK-NEXT:    ccmp w1, #17, #0, ne
315; CHECK-NEXT:    b.eq LBB7_2
316; CHECK-NEXT:  ; %bb.1: ; %if.then
317; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
318; CHECK-NEXT:    bl _foo
319; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
320; CHECK-NEXT:  LBB7_2: ; %if.end
321; CHECK-NEXT:    mov w0, #7 ; =0x7
322; CHECK-NEXT:    ret
323entry:
324  %cmp = icmp eq i32 %a, 0
325  %cmp1 = icmp ne i32 %b, 17
326  %or.cond = or i1 %cmp, %cmp1
327  br i1 %or.cond, label %if.then, label %if.end
328
329if.then:
330  %call = tail call i32 @foo() nounwind
331  br label %if.end
332
333if.end:
334  ret i32 7
335}
336
337; Check that the immediate operand is in range. The ccmp instruction encodes a
338; smaller range of immediates than subs/adds.
339; The ccmp immediates must be in the range 0-31.
340define i32 @immediate_range(i32 %a, i32 %b) nounwind ssp {
341; CHECK-LABEL: immediate_range:
342; CHECK:       ; %bb.0: ; %entry
343; CHECK-NEXT:    cmp w0, #5
344; CHECK-NEXT:    b.eq LBB8_3
345; CHECK-NEXT:  ; %bb.1: ; %entry
346; CHECK-NEXT:    cmp w1, #32
347; CHECK-NEXT:    b.eq LBB8_3
348; CHECK-NEXT:  ; %bb.2: ; %if.end
349; CHECK-NEXT:    mov w0, #7 ; =0x7
350; CHECK-NEXT:    ret
351; CHECK-NEXT:  LBB8_3: ; %if.then
352; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
353; CHECK-NEXT:    bl _foo
354; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
355; CHECK-NEXT:    mov w0, #7 ; =0x7
356; CHECK-NEXT:    ret
357entry:
358  %cmp = icmp eq i32 %a, 5
359  %cmp1 = icmp eq i32 %b, 32
360  %or.cond = or i1 %cmp, %cmp1
361  br i1 %or.cond, label %if.then, label %if.end
362
363if.then:
364  %call = tail call i32 @foo() nounwind
365  br label %if.end
366
367if.end:
368  ret i32 7
369}
370
371; Convert a cbz in the second block.
372define i32 @cbz_second(i32 %a, i32 %b) nounwind ssp {
373; CHECK-LABEL: cbz_second:
374; CHECK:       ; %bb.0: ; %entry
375; CHECK-NEXT:    cmp w0, #0
376; CHECK-NEXT:    ccmp w1, #0, #0, ne
377; CHECK-NEXT:    b.eq LBB9_2
378; CHECK-NEXT:  ; %bb.1: ; %if.then
379; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
380; CHECK-NEXT:    bl _foo
381; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
382; CHECK-NEXT:  LBB9_2: ; %if.end
383; CHECK-NEXT:    mov w0, #7 ; =0x7
384; CHECK-NEXT:    ret
385entry:
386  %cmp = icmp eq i32 %a, 0
387  %cmp1 = icmp ne i32 %b, 0
388  %or.cond = or i1 %cmp, %cmp1
389  br i1 %or.cond, label %if.then, label %if.end
390
391if.then:
392  %call = tail call i32 @foo() nounwind
393  br label %if.end
394
395if.end:
396  ret i32 7
397}
398
399; Convert a cbnz in the second block.
400define i32 @cbnz_second(i32 %a, i32 %b) nounwind ssp {
401; CHECK-LABEL: cbnz_second:
402; CHECK:       ; %bb.0: ; %entry
403; CHECK-NEXT:    cmp w0, #0
404; CHECK-NEXT:    ccmp w1, #0, #4, ne
405; CHECK-NEXT:    b.ne LBB10_2
406; CHECK-NEXT:  ; %bb.1: ; %if.then
407; CHECK-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
408; CHECK-NEXT:    bl _foo
409; CHECK-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
410; CHECK-NEXT:  LBB10_2: ; %if.end
411; CHECK-NEXT:    mov w0, #7 ; =0x7
412; CHECK-NEXT:    ret
413entry:
414  %cmp = icmp eq i32 %a, 0
415  %cmp1 = icmp eq i32 %b, 0
416  %or.cond = or i1 %cmp, %cmp1
417  br i1 %or.cond, label %if.then, label %if.end
418
419if.then:
420  %call = tail call i32 @foo() nounwind
421  br label %if.end
422
423if.end:
424  ret i32 7
425}
426declare i32 @foo()
427
428%str1 = type { %str2 }
429%str2 = type { [24 x i8], ptr, i32, ptr, i32, [4 x i8], ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i8, ptr, ptr, ptr }
430
431; Test case distilled from 126.gcc.
432; The phi in sw.bb.i.i gets multiple operands for the %entry predecessor.
433define void @build_modify_expr() nounwind ssp {
434; CHECK-LABEL: build_modify_expr:
435; CHECK:       ; %bb.0: ; %entry
436; CHECK-NEXT:    ret
437entry:
438  switch i32 undef, label %sw.bb.i.i [
439    i32 69, label %if.end85
440    i32 70, label %if.end85
441    i32 71, label %if.end85
442    i32 72, label %if.end85
443    i32 73, label %if.end85
444    i32 105, label %if.end85
445    i32 106, label %if.end85
446  ]
447
448if.end85:
449  ret void
450
451sw.bb.i.i:
452  %ref.tr.i.i = phi ptr [ %0, %sw.bb.i.i ], [ undef, %entry ]
453  %operands.i.i = getelementptr inbounds %str1, ptr %ref.tr.i.i, i64 0, i32 0, i32 2
454  %0 = load ptr, ptr %operands.i.i, align 8
455  %code1.i.i.phi.trans.insert = getelementptr inbounds %str1, ptr %0, i64 0, i32 0, i32 0, i64 16
456  br label %sw.bb.i.i
457}
458
459define i64 @select_and(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
460; CHECK-LABEL: select_and:
461; CHECK:       ; %bb.0:
462; CHECK-NEXT:    cmp w1, #5
463; CHECK-NEXT:    ccmp w0, w1, #0, ne
464; CHECK-NEXT:    csel x0, x2, x3, lt
465; CHECK-NEXT:    ret
466  %1 = icmp slt i32 %w0, %w1
467  %2 = icmp ne i32 5, %w1
468  %3 = and i1 %1, %2
469  %sel = select i1 %3, i64 %x2, i64 %x3
470  ret i64 %sel
471}
472
473define i64 @select_or(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
474; CHECK-LABEL: select_or:
475; CHECK:       ; %bb.0:
476; CHECK-NEXT:    cmp w1, #5
477; CHECK-NEXT:    ccmp w0, w1, #8, eq
478; CHECK-NEXT:    csel x0, x2, x3, lt
479; CHECK-NEXT:    ret
480  %1 = icmp slt i32 %w0, %w1
481  %2 = icmp ne i32 5, %w1
482  %3 = or i1 %1, %2
483  %sel = select i1 %3, i64 %x2, i64 %x3
484  ret i64 %sel
485}
486
487define float @select_or_float(i32 %w0, i32 %w1, float %x2, float %x3) {
488; CHECK-LABEL: select_or_float:
489; CHECK:       ; %bb.0:
490; CHECK-NEXT:    cmp w1, #5
491; CHECK-NEXT:    ccmp w0, w1, #8, eq
492; CHECK-NEXT:    fcsel s0, s0, s1, lt
493; CHECK-NEXT:    ret
494  %1 = icmp slt i32 %w0, %w1
495  %2 = icmp ne i32 5, %w1
496  %3 = or i1 %1, %2
497  %sel = select i1 %3, float %x2,float %x3
498  ret float %sel
499}
500
501define i64 @gccbug(i64 %x0, i64 %x1) {
502; SDISEL-LABEL: gccbug:
503; SDISEL:       ; %bb.0:
504; SDISEL-NEXT:    cmp x0, #2
505; SDISEL-NEXT:    ccmp x0, #4, #4, ne
506; SDISEL-NEXT:    ccmp x1, #0, #0, eq
507; SDISEL-NEXT:    mov w8, #1 ; =0x1
508; SDISEL-NEXT:    cinc x0, x8, eq
509; SDISEL-NEXT:    ret
510;
511; GISEL-LABEL: gccbug:
512; GISEL:       ; %bb.0:
513; GISEL-NEXT:    cmp x1, #0
514; GISEL-NEXT:    cset w8, eq
515; GISEL-NEXT:    cmp x0, #2
516; GISEL-NEXT:    cset w9, eq
517; GISEL-NEXT:    cmp x0, #4
518; GISEL-NEXT:    cset w10, eq
519; GISEL-NEXT:    orr w9, w10, w9
520; GISEL-NEXT:    and w8, w9, w8
521; GISEL-NEXT:    and x8, x8, #0x1
522; GISEL-NEXT:    add x0, x8, #1
523; GISEL-NEXT:    ret
524  %cmp0 = icmp eq i64 %x1, 0
525  %cmp1 = icmp eq i64 %x0, 2
526  %cmp2 = icmp eq i64 %x0, 4
527
528  %or = or i1 %cmp2, %cmp1
529  %and = and i1 %or, %cmp0
530
531  %sel = select i1 %and, i64 2, i64 1
532  ret i64 %sel
533}
534
535define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) {
536; CHECK-LABEL: select_ororand:
537; CHECK:       ; %bb.0:
538; CHECK-NEXT:    cmp w3, #4
539; CHECK-NEXT:    ccmp w2, #2, #0, gt
540; CHECK-NEXT:    ccmp w1, #13, #2, ge
541; CHECK-NEXT:    ccmp w0, #0, #4, ls
542; CHECK-NEXT:    csel w0, w3, wzr, eq
543; CHECK-NEXT:    ret
544  %c0 = icmp eq i32 %w0, 0
545  %c1 = icmp ugt i32 %w1, 13
546  %c2 = icmp slt i32 %w2, 2
547  %c4 = icmp sgt i32 %w3, 4
548  %or = or i1 %c0, %c1
549  %and = and i1 %c2, %c4
550  %or1 = or i1 %or, %and
551  %sel = select i1 %or1, i32 %w3, i32 0
552  ret i32 %sel
553}
554
555define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) {
556; CHECK-LABEL: select_andor:
557; CHECK:       ; %bb.0:
558; CHECK-NEXT:    cmp w1, w2
559; CHECK-NEXT:    ccmp w0, #0, #4, lt
560; CHECK-NEXT:    ccmp w0, w1, #0, eq
561; CHECK-NEXT:    csel w0, w0, w1, eq
562; CHECK-NEXT:    ret
563  %c0 = icmp eq i32 %v1, %v2
564  %c1 = icmp sge i32 %v2, %v3
565  %c2 = icmp eq i32 %v1, 0
566  %or = or i1 %c2, %c1
567  %and = and i1 %or, %c0
568  %sel = select i1 %and, i32 %v1, i32 %v2
569  ret i32 %sel
570}
571
572define i32 @select_andor32(i32 %v1, i32 %v2, i32 %v3) {
573; SDISEL-LABEL: select_andor32:
574; SDISEL:       ; %bb.0:
575; SDISEL-NEXT:    cmp w1, w2
576; SDISEL-NEXT:    mov w8, #32 ; =0x20
577; SDISEL-NEXT:    ccmp w0, w8, #4, lt
578; SDISEL-NEXT:    ccmp w0, w1, #0, eq
579; SDISEL-NEXT:    csel w0, w0, w1, eq
580; SDISEL-NEXT:    ret
581;
582; GISEL-LABEL: select_andor32:
583; GISEL:       ; %bb.0:
584; GISEL-NEXT:    mov w8, #32 ; =0x20
585; GISEL-NEXT:    cmp w1, w2
586; GISEL-NEXT:    ccmp w0, w8, #4, lt
587; GISEL-NEXT:    ccmp w0, w1, #0, eq
588; GISEL-NEXT:    csel w0, w0, w1, eq
589; GISEL-NEXT:    ret
590  %c0 = icmp eq i32 %v1, %v2
591  %c1 = icmp sge i32 %v2, %v3
592  %c2 = icmp eq i32 %v1, 32
593  %or = or i1 %c2, %c1
594  %and = and i1 %or, %c0
595  %sel = select i1 %and, i32 %v1, i32 %v2
596  ret i32 %sel
597}
598
599define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
600; SDISEL-LABEL: select_noccmp1:
601; SDISEL:       ; %bb.0:
602; SDISEL-NEXT:    cmp x0, #0
603; SDISEL-NEXT:    ccmp x0, #13, #4, lt
604; SDISEL-NEXT:    cset w8, gt
605; SDISEL-NEXT:    cmp x2, #2
606; SDISEL-NEXT:    ccmp x2, #4, #4, lt
607; SDISEL-NEXT:    csinc w8, w8, wzr, le
608; SDISEL-NEXT:    cmp w8, #0
609; SDISEL-NEXT:    csel x0, xzr, x3, ne
610; SDISEL-NEXT:    ret
611;
612; GISEL-LABEL: select_noccmp1:
613; GISEL:       ; %bb.0:
614; GISEL-NEXT:    mov x0, x3
615; GISEL-NEXT:    ret
616  %c0 = icmp slt i64 %v1, 0
617  %c1 = icmp sgt i64 %v1, 13
618  %c2 = icmp slt i64 %v3, 2
619  %c4 = icmp sgt i64 %v3, 4
620  %and0 = and i1 %c0, %c1
621  %and1 = and i1 %c2, %c4
622  %or = or i1 %and0, %and1
623  %sel = select i1 %or, i64 0, i64 %r
624  ret i64 %sel
625}
626
627@g = global i32 0
628
629define i64 @select_noccmp2(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
630; SDISEL-LABEL: select_noccmp2:
631; SDISEL:       ; %bb.0:
632; SDISEL-NEXT:    cmp x0, #0
633; SDISEL-NEXT:    ccmp x0, #13, #0, ge
634; SDISEL-NEXT:    cset w8, gt
635; SDISEL-NEXT:    cmp w8, #0
636; SDISEL-NEXT:    csel x0, xzr, x3, ne
637; SDISEL-NEXT:    sbfx w8, w8, #0, #1
638; SDISEL-NEXT:    adrp x9, _g@PAGE
639; SDISEL-NEXT:    str w8, [x9, _g@PAGEOFF]
640; SDISEL-NEXT:    ret
641;
642; GISEL-LABEL: select_noccmp2:
643; GISEL:       ; %bb.0:
644; GISEL-NEXT:    cmp x0, #14
645; GISEL-NEXT:    cset w8, hs
646; GISEL-NEXT:    tst w8, #0x1
647; GISEL-NEXT:    csel x0, xzr, x3, ne
648; GISEL-NEXT:    sbfx w8, w8, #0, #1
649; GISEL-NEXT:    adrp x9, _g@PAGE
650; GISEL-NEXT:    str w8, [x9, _g@PAGEOFF]
651; GISEL-NEXT:    ret
652  %c0 = icmp slt i64 %v1, 0
653  %c1 = icmp sgt i64 %v1, 13
654  %or = or i1 %c0, %c1
655  %sel = select i1 %or, i64 0, i64 %r
656  %ext = sext i1 %or to i32
657  store volatile i32 %ext, ptr @g
658  ret i64 %sel
659}
660
661; The following is not possible to implement with a single cmp;ccmp;csel
662; sequence.
663define i32 @select_noccmp3(i32 %v0, i32 %v1, i32 %v2) {
664; SDISEL-LABEL: select_noccmp3:
665; SDISEL:       ; %bb.0:
666; SDISEL-NEXT:    cmp w0, #0
667; SDISEL-NEXT:    ccmp w0, #13, #0, ge
668; SDISEL-NEXT:    cset w8, gt
669; SDISEL-NEXT:    cmp w0, #22
670; SDISEL-NEXT:    mov w9, #44 ; =0x2c
671; SDISEL-NEXT:    ccmp w0, w9, #0, ge
672; SDISEL-NEXT:    csel w8, wzr, w8, le
673; SDISEL-NEXT:    cmp w0, #99
674; SDISEL-NEXT:    mov w9, #77 ; =0x4d
675; SDISEL-NEXT:    ccmp w0, w9, #4, ne
676; SDISEL-NEXT:    cset w9, eq
677; SDISEL-NEXT:    tst w8, w9
678; SDISEL-NEXT:    csel w0, w1, w2, ne
679; SDISEL-NEXT:    ret
680;
681; GISEL-LABEL: select_noccmp3:
682; GISEL:       ; %bb.0:
683; GISEL-NEXT:    mov w8, #99 ; =0x63
684; GISEL-NEXT:    sub w9, w0, #45
685; GISEL-NEXT:    cmp w0, #77
686; GISEL-NEXT:    ccmp w0, w8, #4, ne
687; GISEL-NEXT:    ccmn w9, #23, #2, eq
688; GISEL-NEXT:    ccmp w0, #14, #0, lo
689; GISEL-NEXT:    csel w0, w1, w2, hs
690; GISEL-NEXT:    ret
691  %c0 = icmp slt i32 %v0, 0
692  %c1 = icmp sgt i32 %v0, 13
693  %c2 = icmp slt i32 %v0, 22
694  %c3 = icmp sgt i32 %v0, 44
695  %c4 = icmp eq i32 %v0, 99
696  %c5 = icmp eq i32 %v0, 77
697  %or0 = or i1 %c0, %c1
698  %or1 = or i1 %c2, %c3
699  %and0 = and i1 %or0, %or1
700  %or2 = or i1 %c4, %c5
701  %and1 = and i1 %and0, %or2
702  %sel = select i1 %and1, i32 %v1, i32 %v2
703  ret i32 %sel
704}
705
706; Test the IR CCs that expand to two cond codes.
707
708define i32 @select_and_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
709; CHECK-LABEL: select_and_olt_one:
710; CHECK:       ; %bb.0:
711; CHECK-NEXT:    fcmp d0, d1
712; CHECK-NEXT:    fccmp d2, d3, #4, mi
713; CHECK-NEXT:    fccmp d2, d3, #1, ne
714; CHECK-NEXT:    csel w0, w0, w1, vc
715; CHECK-NEXT:    ret
716  %c0 = fcmp olt double %v0, %v1
717  %c1 = fcmp one double %v2, %v3
718  %cr = and i1 %c1, %c0
719  %sel = select i1 %cr, i32 %a, i32 %b
720  ret i32 %sel
721}
722
723define i32 @select_and_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
724; CHECK-LABEL: select_and_one_olt:
725; CHECK:       ; %bb.0:
726; CHECK-NEXT:    fcmp d0, d1
727; CHECK-NEXT:    fccmp d0, d1, #1, ne
728; CHECK-NEXT:    fccmp d2, d3, #0, vc
729; CHECK-NEXT:    csel w0, w0, w1, mi
730; CHECK-NEXT:    ret
731  %c0 = fcmp one double %v0, %v1
732  %c1 = fcmp olt double %v2, %v3
733  %cr = and i1 %c1, %c0
734  %sel = select i1 %cr, i32 %a, i32 %b
735  ret i32 %sel
736}
737
738define i32 @select_and_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
739; CHECK-LABEL: select_and_olt_ueq:
740; CHECK:       ; %bb.0:
741; CHECK-NEXT:    fcmp d0, d1
742; CHECK-NEXT:    fccmp d2, d3, #0, mi
743; CHECK-NEXT:    fccmp d2, d3, #8, le
744; CHECK-NEXT:    csel w0, w0, w1, pl
745; CHECK-NEXT:    ret
746  %c0 = fcmp olt double %v0, %v1
747  %c1 = fcmp ueq double %v2, %v3
748  %cr = and i1 %c1, %c0
749  %sel = select i1 %cr, i32 %a, i32 %b
750  ret i32 %sel
751}
752
753define i32 @select_and_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
754; CHECK-LABEL: select_and_ueq_olt:
755; CHECK:       ; %bb.0:
756; CHECK-NEXT:    fcmp d0, d1
757; CHECK-NEXT:    fccmp d0, d1, #8, le
758; CHECK-NEXT:    fccmp d2, d3, #0, pl
759; CHECK-NEXT:    csel w0, w0, w1, mi
760; CHECK-NEXT:    ret
761  %c0 = fcmp ueq double %v0, %v1
762  %c1 = fcmp olt double %v2, %v3
763  %cr = and i1 %c1, %c0
764  %sel = select i1 %cr, i32 %a, i32 %b
765  ret i32 %sel
766}
767
768define i32 @select_or_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
769; CHECK-LABEL: select_or_olt_one:
770; CHECK:       ; %bb.0:
771; CHECK-NEXT:    fcmp d0, d1
772; CHECK-NEXT:    fccmp d2, d3, #0, pl
773; CHECK-NEXT:    fccmp d2, d3, #8, le
774; CHECK-NEXT:    csel w0, w0, w1, mi
775; CHECK-NEXT:    ret
776  %c0 = fcmp olt double %v0, %v1
777  %c1 = fcmp one double %v2, %v3
778  %cr = or i1 %c1, %c0
779  %sel = select i1 %cr, i32 %a, i32 %b
780  ret i32 %sel
781}
782
783define i32 @select_or_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
784; CHECK-LABEL: select_or_one_olt:
785; CHECK:       ; %bb.0:
786; CHECK-NEXT:    fcmp d0, d1
787; CHECK-NEXT:    fccmp d0, d1, #8, le
788; CHECK-NEXT:    fccmp d2, d3, #8, pl
789; CHECK-NEXT:    csel w0, w0, w1, mi
790; CHECK-NEXT:    ret
791  %c0 = fcmp one double %v0, %v1
792  %c1 = fcmp olt double %v2, %v3
793  %cr = or i1 %c1, %c0
794  %sel = select i1 %cr, i32 %a, i32 %b
795  ret i32 %sel
796}
797
798define i32 @select_or_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
799; CHECK-LABEL: select_or_olt_ueq:
800; CHECK:       ; %bb.0:
801; CHECK-NEXT:    fcmp d0, d1
802; CHECK-NEXT:    fccmp d2, d3, #4, pl
803; CHECK-NEXT:    fccmp d2, d3, #1, ne
804; CHECK-NEXT:    csel w0, w0, w1, vs
805; CHECK-NEXT:    ret
806  %c0 = fcmp olt double %v0, %v1
807  %c1 = fcmp ueq double %v2, %v3
808  %cr = or i1 %c1, %c0
809  %sel = select i1 %cr, i32 %a, i32 %b
810  ret i32 %sel
811}
812
813define i32 @select_or_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
814; CHECK-LABEL: select_or_ueq_olt:
815; CHECK:       ; %bb.0:
816; CHECK-NEXT:    fcmp d0, d1
817; CHECK-NEXT:    fccmp d0, d1, #1, ne
818; CHECK-NEXT:    fccmp d2, d3, #8, vc
819; CHECK-NEXT:    csel w0, w0, w1, mi
820; CHECK-NEXT:    ret
821  %c0 = fcmp ueq double %v0, %v1
822  %c1 = fcmp olt double %v2, %v3
823  %cr = or i1 %c1, %c0
824  %sel = select i1 %cr, i32 %a, i32 %b
825  ret i32 %sel
826}
827
828define i32 @select_or_olt_ogt_ueq(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 {
829; CHECK-LABEL: select_or_olt_ogt_ueq:
830; CHECK:       ; %bb.0:
831; CHECK-NEXT:    fcmp d0, d1
832; CHECK-NEXT:    fccmp d2, d3, #0, pl
833; CHECK-NEXT:    fccmp d4, d5, #4, le
834; CHECK-NEXT:    fccmp d4, d5, #1, ne
835; CHECK-NEXT:    csel w0, w0, w1, vs
836; CHECK-NEXT:    ret
837  %c0 = fcmp olt double %v0, %v1
838  %c1 = fcmp ogt double %v2, %v3
839  %c2 = fcmp ueq double %v4, %v5
840  %c3 = or i1 %c1, %c0
841  %cr = or i1 %c2, %c3
842  %sel = select i1 %cr, i32 %a, i32 %b
843  ret i32 %sel
844}
845
846define i32 @select_or_olt_ueq_ogt(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 {
847; CHECK-LABEL: select_or_olt_ueq_ogt:
848; CHECK:       ; %bb.0:
849; CHECK-NEXT:    fcmp d0, d1
850; CHECK-NEXT:    fccmp d2, d3, #4, pl
851; CHECK-NEXT:    fccmp d2, d3, #1, ne
852; CHECK-NEXT:    fccmp d4, d5, #0, vc
853; CHECK-NEXT:    csel w0, w0, w1, gt
854; CHECK-NEXT:    ret
855  %c0 = fcmp olt double %v0, %v1
856  %c1 = fcmp ueq double %v2, %v3
857  %c2 = fcmp ogt double %v4, %v5
858  %c3 = or i1 %c1, %c0
859  %cr = or i1 %c2, %c3
860  %sel = select i1 %cr, i32 %a, i32 %b
861  ret i32 %sel
862}
863
864; Verify that we correctly promote f16.
865
866define i32 @half_select_and_olt_oge(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 {
867; SDISEL-LABEL: half_select_and_olt_oge:
868; SDISEL:       ; %bb.0:
869; SDISEL-NEXT:    fcvt s1, h1
870; SDISEL-NEXT:    fcvt s0, h0
871; SDISEL-NEXT:    fcmp s0, s1
872; SDISEL-NEXT:    fcvt s0, h3
873; SDISEL-NEXT:    fcvt s1, h2
874; SDISEL-NEXT:    fccmp s1, s0, #8, mi
875; SDISEL-NEXT:    csel w0, w0, w1, ge
876; SDISEL-NEXT:    ret
877;
878; GISEL-LABEL: half_select_and_olt_oge:
879; GISEL:       ; %bb.0:
880; GISEL-NEXT:    fcvt s0, h0
881; GISEL-NEXT:    fcvt s1, h1
882; GISEL-NEXT:    fcvt s2, h2
883; GISEL-NEXT:    fcvt s3, h3
884; GISEL-NEXT:    fcmp s0, s1
885; GISEL-NEXT:    fccmp s2, s3, #8, mi
886; GISEL-NEXT:    csel w0, w0, w1, ge
887; GISEL-NEXT:    ret
888  %c0 = fcmp olt half %v0, %v1
889  %c1 = fcmp oge half %v2, %v3
890  %cr = and i1 %c1, %c0
891  %sel = select i1 %cr, i32 %a, i32 %b
892  ret i32 %sel
893}
894
895define i32 @half_select_and_olt_one(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 {
896; SDISEL-LABEL: half_select_and_olt_one:
897; SDISEL:       ; %bb.0:
898; SDISEL-NEXT:    fcvt s1, h1
899; SDISEL-NEXT:    fcvt s0, h0
900; SDISEL-NEXT:    fcmp s0, s1
901; SDISEL-NEXT:    fcvt s0, h3
902; SDISEL-NEXT:    fcvt s1, h2
903; SDISEL-NEXT:    fccmp s1, s0, #4, mi
904; SDISEL-NEXT:    fccmp s1, s0, #1, ne
905; SDISEL-NEXT:    csel w0, w0, w1, vc
906; SDISEL-NEXT:    ret
907;
908; GISEL-LABEL: half_select_and_olt_one:
909; GISEL:       ; %bb.0:
910; GISEL-NEXT:    fcvt s0, h0
911; GISEL-NEXT:    fcvt s1, h1
912; GISEL-NEXT:    fcvt s2, h2
913; GISEL-NEXT:    fcvt s3, h3
914; GISEL-NEXT:    fcmp s0, s1
915; GISEL-NEXT:    fccmp s2, s3, #4, mi
916; GISEL-NEXT:    fccmp s2, s3, #1, ne
917; GISEL-NEXT:    csel w0, w0, w1, vc
918; GISEL-NEXT:    ret
919  %c0 = fcmp olt half %v0, %v1
920  %c1 = fcmp one half %v2, %v3
921  %cr = and i1 %c1, %c0
922  %sel = select i1 %cr, i32 %a, i32 %b
923  ret i32 %sel
924}
925
926; Also verify that we don't try to generate f128 FCCMPs, using RT calls instead.
927
928define i32 @f128_select_and_olt_oge(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32 %b) #0 {
929; SDISEL-LABEL: f128_select_and_olt_oge:
930; SDISEL:       ; %bb.0:
931; SDISEL-NEXT:    sub sp, sp, #80
932; SDISEL-NEXT:    stp x22, x21, [sp, #32] ; 16-byte Folded Spill
933; SDISEL-NEXT:    stp x20, x19, [sp, #48] ; 16-byte Folded Spill
934; SDISEL-NEXT:    stp x29, x30, [sp, #64] ; 16-byte Folded Spill
935; SDISEL-NEXT:    mov x19, x1
936; SDISEL-NEXT:    mov x20, x0
937; SDISEL-NEXT:    stp q2, q3, [sp] ; 32-byte Folded Spill
938; SDISEL-NEXT:    bl ___lttf2
939; SDISEL-NEXT:    cmp w0, #0
940; SDISEL-NEXT:    cset w21, lt
941; SDISEL-NEXT:    ldp q0, q1, [sp] ; 32-byte Folded Reload
942; SDISEL-NEXT:    bl ___getf2
943; SDISEL-NEXT:    cmp w0, #0
944; SDISEL-NEXT:    cset w8, ge
945; SDISEL-NEXT:    tst w8, w21
946; SDISEL-NEXT:    csel w0, w20, w19, ne
947; SDISEL-NEXT:    ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
948; SDISEL-NEXT:    ldp x20, x19, [sp, #48] ; 16-byte Folded Reload
949; SDISEL-NEXT:    ldp x22, x21, [sp, #32] ; 16-byte Folded Reload
950; SDISEL-NEXT:    add sp, sp, #80
951; SDISEL-NEXT:    ret
952;
953; GISEL-LABEL: f128_select_and_olt_oge:
954; GISEL:       ; %bb.0:
955; GISEL-NEXT:    sub sp, sp, #80
956; GISEL-NEXT:    stp x22, x21, [sp, #32] ; 16-byte Folded Spill
957; GISEL-NEXT:    stp x20, x19, [sp, #48] ; 16-byte Folded Spill
958; GISEL-NEXT:    stp x29, x30, [sp, #64] ; 16-byte Folded Spill
959; GISEL-NEXT:    stp q3, q2, [sp] ; 32-byte Folded Spill
960; GISEL-NEXT:    mov x19, x0
961; GISEL-NEXT:    mov x20, x1
962; GISEL-NEXT:    bl ___lttf2
963; GISEL-NEXT:    mov x21, x0
964; GISEL-NEXT:    ldp q1, q0, [sp] ; 32-byte Folded Reload
965; GISEL-NEXT:    bl ___getf2
966; GISEL-NEXT:    cmp w21, #0
967; GISEL-NEXT:    ccmp w0, #0, #8, lt
968; GISEL-NEXT:    csel w0, w19, w20, ge
969; GISEL-NEXT:    ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
970; GISEL-NEXT:    ldp x20, x19, [sp, #48] ; 16-byte Folded Reload
971; GISEL-NEXT:    ldp x22, x21, [sp, #32] ; 16-byte Folded Reload
972; GISEL-NEXT:    add sp, sp, #80
973; GISEL-NEXT:    ret
974  %c0 = fcmp olt fp128 %v0, %v1
975  %c1 = fcmp oge fp128 %v2, %v3
976  %cr = and i1 %c1, %c0
977  %sel = select i1 %cr, i32 %a, i32 %b
978  ret i32 %sel
979}
980
981; This testcase resembles the core problem of http://llvm.org/PR39550
982; (an OR operation is 2 levels deep but needs to be implemented first)
983define i32 @deep_or(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
984; CHECK-LABEL: deep_or:
985; CHECK:       ; %bb.0:
986; CHECK-NEXT:    cmp w2, #20
987; CHECK-NEXT:    ccmp w2, #15, #4, ne
988; CHECK-NEXT:    ccmp w1, #0, #4, eq
989; CHECK-NEXT:    ccmp w0, #0, #4, ne
990; CHECK-NEXT:    csel w0, w4, w5, ne
991; CHECK-NEXT:    ret
992  %c0 = icmp ne i32 %a0, 0
993  %c1 = icmp ne i32 %a1, 0
994  %c2 = icmp eq i32 %a2, 15
995  %c3 = icmp eq i32 %a2, 20
996
997  %or = or i1 %c2, %c3
998  %and0 = and i1 %or, %c1
999  %and1 = and i1 %and0, %c0
1000  %sel = select i1 %and1, i32 %x, i32 %y
1001  ret i32 %sel
1002}
1003
1004; Variation of deep_or, we still need to implement the OR first though.
1005define i32 @deep_or1(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
1006; CHECK-LABEL: deep_or1:
1007; CHECK:       ; %bb.0:
1008; CHECK-NEXT:    cmp w2, #20
1009; CHECK-NEXT:    ccmp w2, #15, #4, ne
1010; CHECK-NEXT:    ccmp w0, #0, #4, eq
1011; CHECK-NEXT:    ccmp w1, #0, #4, ne
1012; CHECK-NEXT:    csel w0, w4, w5, ne
1013; CHECK-NEXT:    ret
1014  %c0 = icmp ne i32 %a0, 0
1015  %c1 = icmp ne i32 %a1, 0
1016  %c2 = icmp eq i32 %a2, 15
1017  %c3 = icmp eq i32 %a2, 20
1018
1019  %or = or i1 %c2, %c3
1020  %and0 = and i1 %c0, %or
1021  %and1 = and i1 %and0, %c1
1022  %sel = select i1 %and1, i32 %x, i32 %y
1023  ret i32 %sel
1024}
1025
1026; Variation of deep_or, we still need to implement the OR first though.
1027define i32 @deep_or2(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
1028; CHECK-LABEL: deep_or2:
1029; CHECK:       ; %bb.0:
1030; CHECK-NEXT:    cmp w2, #20
1031; CHECK-NEXT:    ccmp w2, #15, #4, ne
1032; CHECK-NEXT:    ccmp w1, #0, #4, eq
1033; CHECK-NEXT:    ccmp w0, #0, #4, ne
1034; CHECK-NEXT:    csel w0, w4, w5, ne
1035; CHECK-NEXT:    ret
1036  %c0 = icmp ne i32 %a0, 0
1037  %c1 = icmp ne i32 %a1, 0
1038  %c2 = icmp eq i32 %a2, 15
1039  %c3 = icmp eq i32 %a2, 20
1040
1041  %or = or i1 %c2, %c3
1042  %and0 = and i1 %c0, %c1
1043  %and1 = and i1 %and0, %or
1044  %sel = select i1 %and1, i32 %x, i32 %y
1045  ret i32 %sel
1046}
1047
1048; This test is trying to test that multiple ccmp's don't get created in a way
1049; that they would have multiple uses. It doesn't seem to.
1050define i32 @multiccmp(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 {
1051; SDISEL-LABEL: multiccmp:
1052; SDISEL:       ; %bb.0: ; %entry
1053; SDISEL-NEXT:    stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill
1054; SDISEL-NEXT:    stp x20, x19, [sp, #16] ; 16-byte Folded Spill
1055; SDISEL-NEXT:    stp x29, x30, [sp, #32] ; 16-byte Folded Spill
1056; SDISEL-NEXT:    mov x19, x5
1057; SDISEL-NEXT:    cmp w0, w1
1058; SDISEL-NEXT:    cset w20, gt
1059; SDISEL-NEXT:    cmp w2, w3
1060; SDISEL-NEXT:    cset w21, ne
1061; SDISEL-NEXT:    tst w20, w21
1062; SDISEL-NEXT:    csel w0, w5, w4, ne
1063; SDISEL-NEXT:    bl _callee
1064; SDISEL-NEXT:    tst w20, w21
1065; SDISEL-NEXT:    csel w0, w0, w19, ne
1066; SDISEL-NEXT:    bl _callee
1067; SDISEL-NEXT:    ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
1068; SDISEL-NEXT:    ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
1069; SDISEL-NEXT:    ldp x22, x21, [sp], #48 ; 16-byte Folded Reload
1070; SDISEL-NEXT:    ret
1071;
1072; GISEL-LABEL: multiccmp:
1073; GISEL:       ; %bb.0: ; %entry
1074; GISEL-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
1075; GISEL-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
1076; GISEL-NEXT:    mov x19, x5
1077; GISEL-NEXT:    cmp w0, w1
1078; GISEL-NEXT:    cset w8, gt
1079; GISEL-NEXT:    cmp w2, w3
1080; GISEL-NEXT:    cset w9, ne
1081; GISEL-NEXT:    and w20, w8, w9
1082; GISEL-NEXT:    tst w20, #0x1
1083; GISEL-NEXT:    csel w0, w5, w4, ne
1084; GISEL-NEXT:    bl _callee
1085; GISEL-NEXT:    tst w20, #0x1
1086; GISEL-NEXT:    csel w0, w0, w19, ne
1087; GISEL-NEXT:    bl _callee
1088; GISEL-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
1089; GISEL-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
1090; GISEL-NEXT:    ret
1091entry:
1092  %c0 = icmp sgt i32 %s0, %s1
1093  %c1 = icmp ne i32 %s2, %s3
1094  %a = and i1 %c0, %c1
1095  %s = select i1 %a, i32 %y, i32 %x
1096  %o = call i32 @callee(i32 %s)
1097  %z1 = select i1 %a, i32 %o, i32 %y
1098  %p = call i32 @callee(i32 %z1)
1099  ret i32 %p
1100}
1101
1102define i32 @multiccmp2(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 {
1103; SDISEL-LABEL: multiccmp2:
1104; SDISEL:       ; %bb.0: ; %entry
1105; SDISEL-NEXT:    stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill
1106; SDISEL-NEXT:    stp x20, x19, [sp, #16] ; 16-byte Folded Spill
1107; SDISEL-NEXT:    stp x29, x30, [sp, #32] ; 16-byte Folded Spill
1108; SDISEL-NEXT:    mov x19, x5
1109; SDISEL-NEXT:    mov x20, x3
1110; SDISEL-NEXT:    mov x21, x0
1111; SDISEL-NEXT:    cmp w0, w1
1112; SDISEL-NEXT:    cset w8, gt
1113; SDISEL-NEXT:    cmp w2, w3
1114; SDISEL-NEXT:    cset w22, ne
1115; SDISEL-NEXT:    tst w8, w22
1116; SDISEL-NEXT:    csel w0, w5, w4, ne
1117; SDISEL-NEXT:    bl _callee
1118; SDISEL-NEXT:    cmp w21, w20
1119; SDISEL-NEXT:    cset w8, eq
1120; SDISEL-NEXT:    tst w22, w8
1121; SDISEL-NEXT:    csel w0, w0, w19, ne
1122; SDISEL-NEXT:    bl _callee
1123; SDISEL-NEXT:    ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
1124; SDISEL-NEXT:    ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
1125; SDISEL-NEXT:    ldp x22, x21, [sp], #48 ; 16-byte Folded Reload
1126; SDISEL-NEXT:    ret
1127;
1128; GISEL-LABEL: multiccmp2:
1129; GISEL:       ; %bb.0: ; %entry
1130; GISEL-NEXT:    stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill
1131; GISEL-NEXT:    stp x20, x19, [sp, #16] ; 16-byte Folded Spill
1132; GISEL-NEXT:    stp x29, x30, [sp, #32] ; 16-byte Folded Spill
1133; GISEL-NEXT:    mov x19, x0
1134; GISEL-NEXT:    mov x20, x3
1135; GISEL-NEXT:    mov x21, x5
1136; GISEL-NEXT:    cmp w0, w1
1137; GISEL-NEXT:    cset w8, gt
1138; GISEL-NEXT:    cmp w2, w3
1139; GISEL-NEXT:    cset w22, ne
1140; GISEL-NEXT:    and w8, w8, w22
1141; GISEL-NEXT:    tst w8, #0x1
1142; GISEL-NEXT:    csel w0, w5, w4, ne
1143; GISEL-NEXT:    bl _callee
1144; GISEL-NEXT:    cmp w19, w20
1145; GISEL-NEXT:    cset w8, eq
1146; GISEL-NEXT:    and w8, w22, w8
1147; GISEL-NEXT:    tst w8, #0x1
1148; GISEL-NEXT:    csel w0, w0, w21, ne
1149; GISEL-NEXT:    bl _callee
1150; GISEL-NEXT:    ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
1151; GISEL-NEXT:    ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
1152; GISEL-NEXT:    ldp x22, x21, [sp], #48 ; 16-byte Folded Reload
1153; GISEL-NEXT:    ret
1154entry:
1155  %c0 = icmp sgt i32 %s0, %s1
1156  %c1 = icmp ne i32 %s2, %s3
1157  %a = and i1 %c0, %c1
1158  %z = zext i1 %a to i32
1159  %s = select i1 %a, i32 %y, i32 %x
1160  %o = call i32 @callee(i32 %s)
1161
1162  %c2 = icmp eq i32 %s0, %s3
1163  %a1 = and i1 %c1, %c2
1164  %z1 = select i1 %a1, i32 %o, i32 %y
1165  %p = call i32 @callee(i32 %z1)
1166  ret i32 %p
1167}
1168declare i32 @callee(i32)
1169
1170define i1 @cmp_and_negative_const(i32 %0, i32 %1) {
1171; SDISEL-LABEL: cmp_and_negative_const:
1172; SDISEL:       ; %bb.0:
1173; SDISEL-NEXT:    cmn w0, #1
1174; SDISEL-NEXT:    ccmn w1, #2, #0, eq
1175; SDISEL-NEXT:    cset w0, eq
1176; SDISEL-NEXT:    ret
1177;
1178; GISEL-LABEL: cmp_and_negative_const:
1179; GISEL:       ; %bb.0:
1180; GISEL-NEXT:    cmn w0, #1
1181; GISEL-NEXT:    cset w8, eq
1182; GISEL-NEXT:    cmn w1, #2
1183; GISEL-NEXT:    cset w9, eq
1184; GISEL-NEXT:    and w0, w8, w9
1185; GISEL-NEXT:    ret
1186  %3 = icmp eq i32 %0, -1
1187  %4 = icmp eq i32 %1, -2
1188  %5 = and i1 %3, %4
1189  ret i1 %5
1190}
1191
1192define i1 @cmp_or_negative_const(i32 %a, i32 %b) {
1193; SDISEL-LABEL: cmp_or_negative_const:
1194; SDISEL:       ; %bb.0:
1195; SDISEL-NEXT:    cmn w0, #1
1196; SDISEL-NEXT:    ccmn w1, #2, #4, ne
1197; SDISEL-NEXT:    cset w0, eq
1198; SDISEL-NEXT:    ret
1199;
1200; GISEL-LABEL: cmp_or_negative_const:
1201; GISEL:       ; %bb.0:
1202; GISEL-NEXT:    cmn w0, #1
1203; GISEL-NEXT:    cset w8, eq
1204; GISEL-NEXT:    cmn w1, #2
1205; GISEL-NEXT:    cset w9, eq
1206; GISEL-NEXT:    orr w0, w8, w9
1207; GISEL-NEXT:    ret
1208  %cmp = icmp eq i32 %a, -1
1209  %cmp1 = icmp eq i32 %b, -2
1210  %or.cond = or i1 %cmp, %cmp1
1211  ret i1 %or.cond
1212}
1213attributes #0 = { nounwind }
1214