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 -global-isel-abort=2 | FileCheck %s --check-prefixes=CHECK,GISEL
4 target triple = "arm64-apple-ios"
6 define 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
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
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
26 %call = tail call i32 @foo() nounwind
33 ; Different condition codes for the two compares.
34 define 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
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
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
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
67 %call = tail call i32 @foo() nounwind
74 ; Second block clobbers the flags, can't convert (easily).
75 define 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
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
112 %cmp = icmp eq i32 %a, 5
113 br i1 %cmp, label %if.then, label %lor.lhs.false
115 lor.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
123 if.then: ; preds = %lor.lhs.false, %entry
124 %call = tail call i32 @foo() nounwind
127 if.end: ; preds = %if.then, %lor.lhs.false
131 ; Second block clobbers the flags and ends with a tbz terminator.
132 define 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
150 %cmp = icmp eq i32 %a, 5
151 br i1 %cmp, label %if.then, label %lor.lhs.false
153 lor.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
162 if.then: ; preds = %lor.lhs.false, %entry
163 %call = tail call i32 @foo() nounwind
166 if.end: ; preds = %if.then, %lor.lhs.false
170 ; Speculatively execute division by zero.
171 ; The sdiv/udiv instructions do not trap when the divisor is zero, so they are
173 define 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
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
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
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
206 %cmp = icmp sgt i32 %a, 0
207 br i1 %cmp, label %land.lhs.true, label %if.end
210 %div = sdiv i32 %b, %a
211 %cmp1 = icmp slt i32 %div, 17
212 br i1 %cmp1, label %if.then, label %if.end
215 %call = tail call i32 @foo() nounwind
222 ; Floating point compare.
223 define 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
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
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
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
260 %cmp = icmp sgt i32 %a, 0
261 br i1 %cmp, label %land.lhs.true, label %if.end
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
270 %call = tail call i32 @foo() nounwind
277 ; Chain multiple compares.
278 define 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
288 ; CHECK-NEXT: LBB6_2: ; %if.then
291 %cmp = icmp sgt i32 %a, %b
292 br i1 %cmp, label %land.lhs.true, label %if.end
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
302 %call = tail call i32 @foo() nounwind
309 ; Convert a cbz in the head block.
310 define 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
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
330 %call = tail call i32 @foo() nounwind
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.
340 define 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
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
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
364 %call = tail call i32 @foo() nounwind
371 ; Convert a cbz in the second block.
372 define 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
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
392 %call = tail call i32 @foo() nounwind
399 ; Convert a cbnz in the second block.
400 define 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
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
420 %call = tail call i32 @foo() nounwind
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 }
431 ; Test case distilled from 126.gcc.
432 ; The phi in sw.bb.i.i gets multiple operands for the %entry predecessor.
433 define void @build_modify_expr() nounwind ssp {
434 ; CHECK-LABEL: build_modify_expr:
435 ; CHECK: ; %bb.0: ; %entry
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
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
459 define i64 @select_and(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
460 ; SDISEL-LABEL: select_and:
462 ; SDISEL-NEXT: cmp w1, #5
463 ; SDISEL-NEXT: ccmp w0, w1, #0, ne
464 ; SDISEL-NEXT: csel x0, x2, x3, lt
467 ; GISEL-LABEL: select_and:
469 ; GISEL-NEXT: mov w8, #5
470 ; GISEL-NEXT: cmp w8, w1
471 ; GISEL-NEXT: ccmp w0, w1, #0, ne
472 ; GISEL-NEXT: csel x0, x2, x3, lt
474 %1 = icmp slt i32 %w0, %w1
475 %2 = icmp ne i32 5, %w1
477 %sel = select i1 %3, i64 %x2, i64 %x3
481 define i64 @select_or(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
482 ; SDISEL-LABEL: select_or:
484 ; SDISEL-NEXT: cmp w1, #5
485 ; SDISEL-NEXT: ccmp w0, w1, #8, eq
486 ; SDISEL-NEXT: csel x0, x2, x3, lt
489 ; GISEL-LABEL: select_or:
491 ; GISEL-NEXT: mov w8, #5
492 ; GISEL-NEXT: cmp w8, w1
493 ; GISEL-NEXT: ccmp w0, w1, #8, eq
494 ; GISEL-NEXT: csel x0, x2, x3, lt
496 %1 = icmp slt i32 %w0, %w1
497 %2 = icmp ne i32 5, %w1
499 %sel = select i1 %3, i64 %x2, i64 %x3
503 define float @select_or_float(i32 %w0, i32 %w1, float %x2, float %x3) {
504 ; SDISEL-LABEL: select_or_float:
506 ; SDISEL-NEXT: cmp w1, #5
507 ; SDISEL-NEXT: ccmp w0, w1, #8, eq
508 ; SDISEL-NEXT: fcsel s0, s0, s1, lt
511 ; GISEL-LABEL: select_or_float:
513 ; GISEL-NEXT: mov w8, #5
514 ; GISEL-NEXT: cmp w8, w1
515 ; GISEL-NEXT: ccmp w0, w1, #8, eq
516 ; GISEL-NEXT: fcsel s0, s0, s1, lt
518 %1 = icmp slt i32 %w0, %w1
519 %2 = icmp ne i32 5, %w1
521 %sel = select i1 %3, float %x2,float %x3
525 define i64 @gccbug(i64 %x0, i64 %x1) {
526 ; SDISEL-LABEL: gccbug:
528 ; SDISEL-NEXT: cmp x0, #2
529 ; SDISEL-NEXT: ccmp x0, #4, #4, ne
530 ; SDISEL-NEXT: ccmp x1, #0, #0, eq
531 ; SDISEL-NEXT: mov w8, #1
532 ; SDISEL-NEXT: cinc x0, x8, eq
535 ; GISEL-LABEL: gccbug:
537 ; GISEL-NEXT: mov w8, #2
538 ; GISEL-NEXT: cmp x0, #2
539 ; GISEL-NEXT: ccmp x0, #4, #4, ne
540 ; GISEL-NEXT: ccmp x1, #0, #0, eq
541 ; GISEL-NEXT: csinc x0, x8, xzr, eq
543 %cmp0 = icmp eq i64 %x1, 0
544 %cmp1 = icmp eq i64 %x0, 2
545 %cmp2 = icmp eq i64 %x0, 4
547 %or = or i1 %cmp2, %cmp1
548 %and = and i1 %or, %cmp0
550 %sel = select i1 %and, i64 2, i64 1
554 define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) {
555 ; CHECK-LABEL: select_ororand:
557 ; CHECK-NEXT: cmp w3, #4
558 ; CHECK-NEXT: ccmp w2, #2, #0, gt
559 ; CHECK-NEXT: ccmp w1, #13, #2, ge
560 ; CHECK-NEXT: ccmp w0, #0, #4, ls
561 ; CHECK-NEXT: csel w0, w3, wzr, eq
563 %c0 = icmp eq i32 %w0, 0
564 %c1 = icmp ugt i32 %w1, 13
565 %c2 = icmp slt i32 %w2, 2
566 %c4 = icmp sgt i32 %w3, 4
568 %and = and i1 %c2, %c4
569 %or1 = or i1 %or, %and
570 %sel = select i1 %or1, i32 %w3, i32 0
574 define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) {
575 ; CHECK-LABEL: select_andor:
577 ; CHECK-NEXT: cmp w1, w2
578 ; CHECK-NEXT: ccmp w0, #0, #4, lt
579 ; CHECK-NEXT: ccmp w0, w1, #0, eq
580 ; CHECK-NEXT: csel w0, w0, w1, eq
582 %c0 = icmp eq i32 %v1, %v2
583 %c1 = icmp sge i32 %v2, %v3
584 %c2 = icmp eq i32 %v1, 0
586 %and = and i1 %or, %c0
587 %sel = select i1 %and, i32 %v1, i32 %v2
591 define i32 @select_andor32(i32 %v1, i32 %v2, i32 %v3) {
592 ; SDISEL-LABEL: select_andor32:
594 ; SDISEL-NEXT: cmp w1, w2
595 ; SDISEL-NEXT: mov w8, #32
596 ; SDISEL-NEXT: ccmp w0, w8, #4, lt
597 ; SDISEL-NEXT: ccmp w0, w1, #0, eq
598 ; SDISEL-NEXT: csel w0, w0, w1, eq
601 ; GISEL-LABEL: select_andor32:
603 ; GISEL-NEXT: mov w8, #32
604 ; GISEL-NEXT: cmp w1, w2
605 ; GISEL-NEXT: ccmp w0, w8, #4, lt
606 ; GISEL-NEXT: ccmp w0, w1, #0, eq
607 ; GISEL-NEXT: csel w0, w0, w1, eq
609 %c0 = icmp eq i32 %v1, %v2
610 %c1 = icmp sge i32 %v2, %v3
611 %c2 = icmp eq i32 %v1, 32
613 %and = and i1 %or, %c0
614 %sel = select i1 %and, i32 %v1, i32 %v2
618 define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
619 ; SDISEL-LABEL: select_noccmp1:
621 ; SDISEL-NEXT: cmp x0, #0
622 ; SDISEL-NEXT: ccmp x0, #13, #4, lt
623 ; SDISEL-NEXT: cset w8, gt
624 ; SDISEL-NEXT: cmp x2, #2
625 ; SDISEL-NEXT: ccmp x2, #4, #4, lt
626 ; SDISEL-NEXT: csinc w8, w8, wzr, le
627 ; SDISEL-NEXT: cmp w8, #0
628 ; SDISEL-NEXT: csel x0, xzr, x3, ne
631 ; GISEL-LABEL: select_noccmp1:
633 ; GISEL-NEXT: cmp x0, #0
634 ; GISEL-NEXT: cset w8, lt
635 ; GISEL-NEXT: cmp x0, #13
636 ; GISEL-NEXT: cset w9, gt
637 ; GISEL-NEXT: cmp x2, #2
638 ; GISEL-NEXT: cset w10, lt
639 ; GISEL-NEXT: cmp x2, #4
640 ; GISEL-NEXT: cset w11, gt
641 ; GISEL-NEXT: and w8, w8, w9
642 ; GISEL-NEXT: and w9, w10, w11
643 ; GISEL-NEXT: orr w8, w8, w9
644 ; GISEL-NEXT: tst w8, #0x1
645 ; GISEL-NEXT: csel x0, xzr, x3, ne
647 %c0 = icmp slt i64 %v1, 0
648 %c1 = icmp sgt i64 %v1, 13
649 %c2 = icmp slt i64 %v3, 2
650 %c4 = icmp sgt i64 %v3, 4
651 %and0 = and i1 %c0, %c1
652 %and1 = and i1 %c2, %c4
653 %or = or i1 %and0, %and1
654 %sel = select i1 %or, i64 0, i64 %r
660 define i64 @select_noccmp2(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
661 ; SDISEL-LABEL: select_noccmp2:
663 ; SDISEL-NEXT: cmp x0, #0
664 ; SDISEL-NEXT: ccmp x0, #13, #0, ge
665 ; SDISEL-NEXT: cset w8, gt
666 ; SDISEL-NEXT: cmp w8, #0
667 ; SDISEL-NEXT: csel x0, xzr, x3, ne
668 ; SDISEL-NEXT: sbfx w8, w8, #0, #1
669 ; SDISEL-NEXT: adrp x9, _g@PAGE
670 ; SDISEL-NEXT: str w8, [x9, _g@PAGEOFF]
673 ; GISEL-LABEL: select_noccmp2:
675 ; GISEL-NEXT: cmp x0, #0
676 ; GISEL-NEXT: cset w8, lt
677 ; GISEL-NEXT: cmp x0, #13
678 ; GISEL-NEXT: cset w9, gt
679 ; GISEL-NEXT: orr w8, w8, w9
680 ; GISEL-NEXT: tst w8, #0x1
681 ; GISEL-NEXT: csel x0, xzr, x3, ne
682 ; GISEL-NEXT: sbfx w8, w8, #0, #1
683 ; GISEL-NEXT: adrp x9, _g@PAGE
684 ; GISEL-NEXT: str w8, [x9, _g@PAGEOFF]
686 %c0 = icmp slt i64 %v1, 0
687 %c1 = icmp sgt i64 %v1, 13
689 %sel = select i1 %or, i64 0, i64 %r
690 %ext = sext i1 %or to i32
691 store volatile i32 %ext, ptr @g
695 ; The following is not possible to implement with a single cmp;ccmp;csel
697 define i32 @select_noccmp3(i32 %v0, i32 %v1, i32 %v2) {
698 ; SDISEL-LABEL: select_noccmp3:
700 ; SDISEL-NEXT: cmp w0, #0
701 ; SDISEL-NEXT: ccmp w0, #13, #0, ge
702 ; SDISEL-NEXT: cset w8, gt
703 ; SDISEL-NEXT: cmp w0, #22
704 ; SDISEL-NEXT: mov w9, #44
705 ; SDISEL-NEXT: ccmp w0, w9, #0, ge
706 ; SDISEL-NEXT: csel w8, wzr, w8, le
707 ; SDISEL-NEXT: cmp w0, #99
708 ; SDISEL-NEXT: mov w9, #77
709 ; SDISEL-NEXT: ccmp w0, w9, #4, ne
710 ; SDISEL-NEXT: cset w9, eq
711 ; SDISEL-NEXT: tst w8, w9
712 ; SDISEL-NEXT: csel w0, w1, w2, ne
715 ; GISEL-LABEL: select_noccmp3:
717 ; GISEL-NEXT: cmp w0, #0
718 ; GISEL-NEXT: cset w8, lt
719 ; GISEL-NEXT: cmp w0, #13
720 ; GISEL-NEXT: cset w9, gt
721 ; GISEL-NEXT: cmp w0, #22
722 ; GISEL-NEXT: cset w10, lt
723 ; GISEL-NEXT: cmp w0, #44
724 ; GISEL-NEXT: cset w11, gt
725 ; GISEL-NEXT: cmp w0, #99
726 ; GISEL-NEXT: cset w12, eq
727 ; GISEL-NEXT: cmp w0, #77
728 ; GISEL-NEXT: cset w13, eq
729 ; GISEL-NEXT: orr w8, w8, w9
730 ; GISEL-NEXT: orr w9, w10, w11
731 ; GISEL-NEXT: and w8, w8, w9
732 ; GISEL-NEXT: orr w9, w12, w13
733 ; GISEL-NEXT: and w8, w8, w9
734 ; GISEL-NEXT: tst w8, #0x1
735 ; GISEL-NEXT: csel w0, w1, w2, ne
737 %c0 = icmp slt i32 %v0, 0
738 %c1 = icmp sgt i32 %v0, 13
739 %c2 = icmp slt i32 %v0, 22
740 %c3 = icmp sgt i32 %v0, 44
741 %c4 = icmp eq i32 %v0, 99
742 %c5 = icmp eq i32 %v0, 77
743 %or0 = or i1 %c0, %c1
744 %or1 = or i1 %c2, %c3
745 %and0 = and i1 %or0, %or1
746 %or2 = or i1 %c4, %c5
747 %and1 = and i1 %and0, %or2
748 %sel = select i1 %and1, i32 %v1, i32 %v2
752 ; Test the IR CCs that expand to two cond codes.
754 define i32 @select_and_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
755 ; CHECK-LABEL: select_and_olt_one:
757 ; CHECK-NEXT: fcmp d0, d1
758 ; CHECK-NEXT: fccmp d2, d3, #4, mi
759 ; CHECK-NEXT: fccmp d2, d3, #1, ne
760 ; CHECK-NEXT: csel w0, w0, w1, vc
762 %c0 = fcmp olt double %v0, %v1
763 %c1 = fcmp one double %v2, %v3
764 %cr = and i1 %c1, %c0
765 %sel = select i1 %cr, i32 %a, i32 %b
769 define i32 @select_and_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
770 ; CHECK-LABEL: select_and_one_olt:
772 ; CHECK-NEXT: fcmp d0, d1
773 ; CHECK-NEXT: fccmp d0, d1, #1, ne
774 ; CHECK-NEXT: fccmp d2, d3, #0, vc
775 ; CHECK-NEXT: csel w0, w0, w1, mi
777 %c0 = fcmp one double %v0, %v1
778 %c1 = fcmp olt double %v2, %v3
779 %cr = and i1 %c1, %c0
780 %sel = select i1 %cr, i32 %a, i32 %b
784 define i32 @select_and_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
785 ; CHECK-LABEL: select_and_olt_ueq:
787 ; CHECK-NEXT: fcmp d0, d1
788 ; CHECK-NEXT: fccmp d2, d3, #0, mi
789 ; CHECK-NEXT: fccmp d2, d3, #8, le
790 ; CHECK-NEXT: csel w0, w0, w1, pl
792 %c0 = fcmp olt double %v0, %v1
793 %c1 = fcmp ueq double %v2, %v3
794 %cr = and i1 %c1, %c0
795 %sel = select i1 %cr, i32 %a, i32 %b
799 define i32 @select_and_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
800 ; CHECK-LABEL: select_and_ueq_olt:
802 ; CHECK-NEXT: fcmp d0, d1
803 ; CHECK-NEXT: fccmp d0, d1, #8, le
804 ; CHECK-NEXT: fccmp d2, d3, #0, pl
805 ; CHECK-NEXT: csel w0, w0, w1, mi
807 %c0 = fcmp ueq double %v0, %v1
808 %c1 = fcmp olt double %v2, %v3
809 %cr = and i1 %c1, %c0
810 %sel = select i1 %cr, i32 %a, i32 %b
814 define i32 @select_or_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
815 ; CHECK-LABEL: select_or_olt_one:
817 ; CHECK-NEXT: fcmp d0, d1
818 ; CHECK-NEXT: fccmp d2, d3, #0, pl
819 ; CHECK-NEXT: fccmp d2, d3, #8, le
820 ; CHECK-NEXT: csel w0, w0, w1, mi
822 %c0 = fcmp olt double %v0, %v1
823 %c1 = fcmp one double %v2, %v3
825 %sel = select i1 %cr, i32 %a, i32 %b
829 define i32 @select_or_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
830 ; CHECK-LABEL: select_or_one_olt:
832 ; CHECK-NEXT: fcmp d0, d1
833 ; CHECK-NEXT: fccmp d0, d1, #8, le
834 ; CHECK-NEXT: fccmp d2, d3, #8, pl
835 ; CHECK-NEXT: csel w0, w0, w1, mi
837 %c0 = fcmp one double %v0, %v1
838 %c1 = fcmp olt double %v2, %v3
840 %sel = select i1 %cr, i32 %a, i32 %b
844 define i32 @select_or_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
845 ; CHECK-LABEL: select_or_olt_ueq:
847 ; CHECK-NEXT: fcmp d0, d1
848 ; CHECK-NEXT: fccmp d2, d3, #4, pl
849 ; CHECK-NEXT: fccmp d2, d3, #1, ne
850 ; CHECK-NEXT: csel w0, w0, w1, vs
852 %c0 = fcmp olt double %v0, %v1
853 %c1 = fcmp ueq double %v2, %v3
855 %sel = select i1 %cr, i32 %a, i32 %b
859 define i32 @select_or_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
860 ; CHECK-LABEL: select_or_ueq_olt:
862 ; CHECK-NEXT: fcmp d0, d1
863 ; CHECK-NEXT: fccmp d0, d1, #1, ne
864 ; CHECK-NEXT: fccmp d2, d3, #8, vc
865 ; CHECK-NEXT: csel w0, w0, w1, mi
867 %c0 = fcmp ueq double %v0, %v1
868 %c1 = fcmp olt double %v2, %v3
870 %sel = select i1 %cr, i32 %a, i32 %b
874 define i32 @select_or_olt_ogt_ueq(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 {
875 ; CHECK-LABEL: select_or_olt_ogt_ueq:
877 ; CHECK-NEXT: fcmp d0, d1
878 ; CHECK-NEXT: fccmp d2, d3, #0, pl
879 ; CHECK-NEXT: fccmp d4, d5, #4, le
880 ; CHECK-NEXT: fccmp d4, d5, #1, ne
881 ; CHECK-NEXT: csel w0, w0, w1, vs
883 %c0 = fcmp olt double %v0, %v1
884 %c1 = fcmp ogt double %v2, %v3
885 %c2 = fcmp ueq double %v4, %v5
888 %sel = select i1 %cr, i32 %a, i32 %b
892 define i32 @select_or_olt_ueq_ogt(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 {
893 ; CHECK-LABEL: select_or_olt_ueq_ogt:
895 ; CHECK-NEXT: fcmp d0, d1
896 ; CHECK-NEXT: fccmp d2, d3, #4, pl
897 ; CHECK-NEXT: fccmp d2, d3, #1, ne
898 ; CHECK-NEXT: fccmp d4, d5, #0, vc
899 ; CHECK-NEXT: csel w0, w0, w1, gt
901 %c0 = fcmp olt double %v0, %v1
902 %c1 = fcmp ueq double %v2, %v3
903 %c2 = fcmp ogt double %v4, %v5
906 %sel = select i1 %cr, i32 %a, i32 %b
910 ; Verify that we correctly promote f16.
912 define i32 @half_select_and_olt_oge(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 {
913 ; SDISEL-LABEL: half_select_and_olt_oge:
915 ; SDISEL-NEXT: fcvt s1, h1
916 ; SDISEL-NEXT: fcvt s0, h0
917 ; SDISEL-NEXT: fcmp s0, s1
918 ; SDISEL-NEXT: fcvt s0, h3
919 ; SDISEL-NEXT: fcvt s1, h2
920 ; SDISEL-NEXT: fccmp s1, s0, #8, mi
921 ; SDISEL-NEXT: csel w0, w0, w1, ge
924 ; GISEL-LABEL: half_select_and_olt_oge:
926 ; GISEL-NEXT: fcvt s0, h0
927 ; GISEL-NEXT: fcvt s1, h1
928 ; GISEL-NEXT: fcvt s2, h2
929 ; GISEL-NEXT: fcvt s3, h3
930 ; GISEL-NEXT: fcmp s0, s1
931 ; GISEL-NEXT: fccmp s2, s3, #8, mi
932 ; GISEL-NEXT: csel w0, w0, w1, ge
934 %c0 = fcmp olt half %v0, %v1
935 %c1 = fcmp oge half %v2, %v3
936 %cr = and i1 %c1, %c0
937 %sel = select i1 %cr, i32 %a, i32 %b
941 define i32 @half_select_and_olt_one(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 {
942 ; SDISEL-LABEL: half_select_and_olt_one:
944 ; SDISEL-NEXT: fcvt s1, h1
945 ; SDISEL-NEXT: fcvt s0, h0
946 ; SDISEL-NEXT: fcmp s0, s1
947 ; SDISEL-NEXT: fcvt s0, h3
948 ; SDISEL-NEXT: fcvt s1, h2
949 ; SDISEL-NEXT: fccmp s1, s0, #4, mi
950 ; SDISEL-NEXT: fccmp s1, s0, #1, ne
951 ; SDISEL-NEXT: csel w0, w0, w1, vc
954 ; GISEL-LABEL: half_select_and_olt_one:
956 ; GISEL-NEXT: fcvt s0, h0
957 ; GISEL-NEXT: fcvt s1, h1
958 ; GISEL-NEXT: fcvt s2, h2
959 ; GISEL-NEXT: fcvt s3, h3
960 ; GISEL-NEXT: fcmp s0, s1
961 ; GISEL-NEXT: fccmp s2, s3, #4, mi
962 ; GISEL-NEXT: fccmp s2, s3, #1, ne
963 ; GISEL-NEXT: csel w0, w0, w1, vc
965 %c0 = fcmp olt half %v0, %v1
966 %c1 = fcmp one half %v2, %v3
967 %cr = and i1 %c1, %c0
968 %sel = select i1 %cr, i32 %a, i32 %b
972 ; Also verify that we don't try to generate f128 FCCMPs, using RT calls instead.
974 define i32 @f128_select_and_olt_oge(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32 %b) #0 {
975 ; CHECK-LABEL: f128_select_and_olt_oge:
977 ; CHECK-NEXT: sub sp, sp, #80
978 ; CHECK-NEXT: stp x22, x21, [sp, #32] ; 16-byte Folded Spill
979 ; CHECK-NEXT: stp x20, x19, [sp, #48] ; 16-byte Folded Spill
980 ; CHECK-NEXT: stp x29, x30, [sp, #64] ; 16-byte Folded Spill
981 ; CHECK-NEXT: mov x19, x1
982 ; CHECK-NEXT: mov x20, x0
983 ; CHECK-NEXT: stp q2, q3, [sp] ; 32-byte Folded Spill
984 ; CHECK-NEXT: bl ___lttf2
985 ; CHECK-NEXT: cmp w0, #0
986 ; CHECK-NEXT: cset w21, lt
987 ; CHECK-NEXT: ldp q0, q1, [sp] ; 32-byte Folded Reload
988 ; CHECK-NEXT: bl ___getf2
989 ; CHECK-NEXT: cmp w0, #0
990 ; CHECK-NEXT: cset w8, ge
991 ; CHECK-NEXT: tst w8, w21
992 ; CHECK-NEXT: csel w0, w20, w19, ne
993 ; CHECK-NEXT: ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
994 ; CHECK-NEXT: ldp x20, x19, [sp, #48] ; 16-byte Folded Reload
995 ; CHECK-NEXT: ldp x22, x21, [sp, #32] ; 16-byte Folded Reload
996 ; CHECK-NEXT: add sp, sp, #80
998 %c0 = fcmp olt fp128 %v0, %v1
999 %c1 = fcmp oge fp128 %v2, %v3
1000 %cr = and i1 %c1, %c0
1001 %sel = select i1 %cr, i32 %a, i32 %b
1005 ; This testcase resembles the core problem of http://llvm.org/PR39550
1006 ; (an OR operation is 2 levels deep but needs to be implemented first)
1007 define i32 @deep_or(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
1008 ; CHECK-LABEL: deep_or:
1010 ; CHECK-NEXT: cmp w2, #20
1011 ; CHECK-NEXT: ccmp w2, #15, #4, ne
1012 ; CHECK-NEXT: ccmp w1, #0, #4, eq
1013 ; CHECK-NEXT: ccmp w0, #0, #4, ne
1014 ; CHECK-NEXT: csel w0, w4, w5, ne
1016 %c0 = icmp ne i32 %a0, 0
1017 %c1 = icmp ne i32 %a1, 0
1018 %c2 = icmp eq i32 %a2, 15
1019 %c3 = icmp eq i32 %a2, 20
1021 %or = or i1 %c2, %c3
1022 %and0 = and i1 %or, %c1
1023 %and1 = and i1 %and0, %c0
1024 %sel = select i1 %and1, i32 %x, i32 %y
1028 ; Variation of deep_or, we still need to implement the OR first though.
1029 define i32 @deep_or1(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
1030 ; CHECK-LABEL: deep_or1:
1032 ; CHECK-NEXT: cmp w2, #20
1033 ; CHECK-NEXT: ccmp w2, #15, #4, ne
1034 ; CHECK-NEXT: ccmp w0, #0, #4, eq
1035 ; CHECK-NEXT: ccmp w1, #0, #4, ne
1036 ; CHECK-NEXT: csel w0, w4, w5, ne
1038 %c0 = icmp ne i32 %a0, 0
1039 %c1 = icmp ne i32 %a1, 0
1040 %c2 = icmp eq i32 %a2, 15
1041 %c3 = icmp eq i32 %a2, 20
1043 %or = or i1 %c2, %c3
1044 %and0 = and i1 %c0, %or
1045 %and1 = and i1 %and0, %c1
1046 %sel = select i1 %and1, i32 %x, i32 %y
1050 ; Variation of deep_or, we still need to implement the OR first though.
1051 define i32 @deep_or2(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
1052 ; CHECK-LABEL: deep_or2:
1054 ; CHECK-NEXT: cmp w2, #20
1055 ; CHECK-NEXT: ccmp w2, #15, #4, ne
1056 ; CHECK-NEXT: ccmp w1, #0, #4, eq
1057 ; CHECK-NEXT: ccmp w0, #0, #4, ne
1058 ; CHECK-NEXT: csel w0, w4, w5, ne
1060 %c0 = icmp ne i32 %a0, 0
1061 %c1 = icmp ne i32 %a1, 0
1062 %c2 = icmp eq i32 %a2, 15
1063 %c3 = icmp eq i32 %a2, 20
1065 %or = or i1 %c2, %c3
1066 %and0 = and i1 %c0, %c1
1067 %and1 = and i1 %and0, %or
1068 %sel = select i1 %and1, i32 %x, i32 %y
1072 ; This test is trying to test that multiple ccmp's don't get created in a way
1073 ; that they would have multiple uses. It doesn't seem to.
1074 define i32 @multiccmp(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 {
1075 ; SDISEL-LABEL: multiccmp:
1076 ; SDISEL: ; %bb.0: ; %entry
1077 ; SDISEL-NEXT: stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill
1078 ; SDISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill
1079 ; SDISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill
1080 ; SDISEL-NEXT: mov x19, x5
1081 ; SDISEL-NEXT: cmp w0, w1
1082 ; SDISEL-NEXT: cset w20, gt
1083 ; SDISEL-NEXT: cmp w2, w3
1084 ; SDISEL-NEXT: cset w21, ne
1085 ; SDISEL-NEXT: tst w20, w21
1086 ; SDISEL-NEXT: csel w0, w5, w4, ne
1087 ; SDISEL-NEXT: bl _callee
1088 ; SDISEL-NEXT: tst w20, w21
1089 ; SDISEL-NEXT: csel w0, w0, w19, ne
1090 ; SDISEL-NEXT: bl _callee
1091 ; SDISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
1092 ; SDISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
1093 ; SDISEL-NEXT: ldp x22, x21, [sp], #48 ; 16-byte Folded Reload
1096 ; GISEL-LABEL: multiccmp:
1097 ; GISEL: ; %bb.0: ; %entry
1098 ; GISEL-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
1099 ; GISEL-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
1100 ; GISEL-NEXT: mov x19, x5
1101 ; GISEL-NEXT: cmp w0, w1
1102 ; GISEL-NEXT: cset w8, gt
1103 ; GISEL-NEXT: cmp w2, w3
1104 ; GISEL-NEXT: cset w9, ne
1105 ; GISEL-NEXT: and w20, w8, w9
1106 ; GISEL-NEXT: tst w20, #0x1
1107 ; GISEL-NEXT: csel w0, w5, w4, ne
1108 ; GISEL-NEXT: bl _callee
1109 ; GISEL-NEXT: tst w20, #0x1
1110 ; GISEL-NEXT: csel w0, w0, w19, ne
1111 ; GISEL-NEXT: bl _callee
1112 ; GISEL-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
1113 ; GISEL-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
1116 %c0 = icmp sgt i32 %s0, %s1
1117 %c1 = icmp ne i32 %s2, %s3
1118 %a = and i1 %c0, %c1
1119 %s = select i1 %a, i32 %y, i32 %x
1120 %o = call i32 @callee(i32 %s)
1121 %z1 = select i1 %a, i32 %o, i32 %y
1122 %p = call i32 @callee(i32 %z1)
1126 define i32 @multiccmp2(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 {
1127 ; SDISEL-LABEL: multiccmp2:
1128 ; SDISEL: ; %bb.0: ; %entry
1129 ; SDISEL-NEXT: stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill
1130 ; SDISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill
1131 ; SDISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill
1132 ; SDISEL-NEXT: mov x19, x5
1133 ; SDISEL-NEXT: mov x20, x3
1134 ; SDISEL-NEXT: mov x21, x0
1135 ; SDISEL-NEXT: cmp w0, w1
1136 ; SDISEL-NEXT: cset w8, gt
1137 ; SDISEL-NEXT: cmp w2, w3
1138 ; SDISEL-NEXT: cset w22, ne
1139 ; SDISEL-NEXT: tst w8, w22
1140 ; SDISEL-NEXT: csel w0, w5, w4, ne
1141 ; SDISEL-NEXT: bl _callee
1142 ; SDISEL-NEXT: cmp w21, w20
1143 ; SDISEL-NEXT: cset w8, eq
1144 ; SDISEL-NEXT: tst w22, w8
1145 ; SDISEL-NEXT: csel w0, w0, w19, ne
1146 ; SDISEL-NEXT: bl _callee
1147 ; SDISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
1148 ; SDISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
1149 ; SDISEL-NEXT: ldp x22, x21, [sp], #48 ; 16-byte Folded Reload
1152 ; GISEL-LABEL: multiccmp2:
1153 ; GISEL: ; %bb.0: ; %entry
1154 ; GISEL-NEXT: stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill
1155 ; GISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill
1156 ; GISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill
1157 ; GISEL-NEXT: mov x19, x0
1158 ; GISEL-NEXT: mov x20, x3
1159 ; GISEL-NEXT: mov x21, x5
1160 ; GISEL-NEXT: cmp w0, w1
1161 ; GISEL-NEXT: cset w8, gt
1162 ; GISEL-NEXT: cmp w2, w3
1163 ; GISEL-NEXT: cset w22, ne
1164 ; GISEL-NEXT: and w8, w8, w22
1165 ; GISEL-NEXT: tst w8, #0x1
1166 ; GISEL-NEXT: csel w0, w5, w4, ne
1167 ; GISEL-NEXT: bl _callee
1168 ; GISEL-NEXT: cmp w19, w20
1169 ; GISEL-NEXT: cset w8, eq
1170 ; GISEL-NEXT: and w8, w22, w8
1171 ; GISEL-NEXT: tst w8, #0x1
1172 ; GISEL-NEXT: csel w0, w0, w21, ne
1173 ; GISEL-NEXT: bl _callee
1174 ; GISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
1175 ; GISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
1176 ; GISEL-NEXT: ldp x22, x21, [sp], #48 ; 16-byte Folded Reload
1179 %c0 = icmp sgt i32 %s0, %s1
1180 %c1 = icmp ne i32 %s2, %s3
1181 %a = and i1 %c0, %c1
1182 %z = zext i1 %a to i32
1183 %s = select i1 %a, i32 %y, i32 %x
1184 %o = call i32 @callee(i32 %s)
1186 %c2 = icmp eq i32 %s0, %s3
1187 %a1 = and i1 %c1, %c2
1188 %z1 = select i1 %a1, i32 %o, i32 %y
1189 %p = call i32 @callee(i32 %z1)
1192 declare i32 @callee(i32)
1194 define i1 @cmp_and_negative_const(i32 %0, i32 %1) {
1195 ; SDISEL-LABEL: cmp_and_negative_const:
1197 ; SDISEL-NEXT: cmn w0, #1
1198 ; SDISEL-NEXT: ccmn w1, #2, #0, eq
1199 ; SDISEL-NEXT: cset w0, eq
1202 ; GISEL-LABEL: cmp_and_negative_const:
1204 ; GISEL-NEXT: cmn w0, #1
1205 ; GISEL-NEXT: cset w8, eq
1206 ; GISEL-NEXT: cmn w1, #2
1207 ; GISEL-NEXT: cset w9, eq
1208 ; GISEL-NEXT: and w0, w8, w9
1210 %3 = icmp eq i32 %0, -1
1211 %4 = icmp eq i32 %1, -2
1216 define i1 @cmp_or_negative_const(i32 %a, i32 %b) {
1217 ; SDISEL-LABEL: cmp_or_negative_const:
1219 ; SDISEL-NEXT: cmn w0, #1
1220 ; SDISEL-NEXT: ccmn w1, #2, #4, ne
1221 ; SDISEL-NEXT: cset w0, eq
1224 ; GISEL-LABEL: cmp_or_negative_const:
1226 ; GISEL-NEXT: cmn w0, #1
1227 ; GISEL-NEXT: cset w8, eq
1228 ; GISEL-NEXT: cmn w1, #2
1229 ; GISEL-NEXT: cset w9, eq
1230 ; GISEL-NEXT: orr w0, w8, w9
1232 %cmp = icmp eq i32 %a, -1
1233 %cmp1 = icmp eq i32 %b, -2
1234 %or.cond = or i1 %cmp, %cmp1
1237 attributes #0 = { nounwind }