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
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 ; =0x7
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 ; =0x7
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 ; =0x7
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 ; =0x7
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
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 ; =0x7
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 ; =0x7
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
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
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
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 ; =0x7
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
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
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
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 ; =0x7
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 ; =0x7
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
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 ; =0x7
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 ; =0x7
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 ; CHECK-LABEL: select_and:
462 ; CHECK-NEXT: cmp w1, #5
463 ; CHECK-NEXT: ccmp w0, w1, #0, ne
464 ; CHECK-NEXT: csel x0, x2, x3, lt
466 %1 = icmp slt i32 %w0, %w1
467 %2 = icmp ne i32 5, %w1
469 %sel = select i1 %3, i64 %x2, i64 %x3
473 define i64 @select_or(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
474 ; CHECK-LABEL: select_or:
476 ; CHECK-NEXT: cmp w1, #5
477 ; CHECK-NEXT: ccmp w0, w1, #8, eq
478 ; CHECK-NEXT: csel x0, x2, x3, lt
480 %1 = icmp slt i32 %w0, %w1
481 %2 = icmp ne i32 5, %w1
483 %sel = select i1 %3, i64 %x2, i64 %x3
487 define float @select_or_float(i32 %w0, i32 %w1, float %x2, float %x3) {
488 ; CHECK-LABEL: select_or_float:
490 ; CHECK-NEXT: cmp w1, #5
491 ; CHECK-NEXT: ccmp w0, w1, #8, eq
492 ; CHECK-NEXT: fcsel s0, s0, s1, lt
494 %1 = icmp slt i32 %w0, %w1
495 %2 = icmp ne i32 5, %w1
497 %sel = select i1 %3, float %x2,float %x3
501 define i64 @gccbug(i64 %x0, i64 %x1) {
502 ; SDISEL-LABEL: gccbug:
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
511 ; GISEL-LABEL: gccbug:
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
524 %cmp0 = icmp eq i64 %x1, 0
525 %cmp1 = icmp eq i64 %x0, 2
526 %cmp2 = icmp eq i64 %x0, 4
528 %or = or i1 %cmp2, %cmp1
529 %and = and i1 %or, %cmp0
531 %sel = select i1 %and, i64 2, i64 1
535 define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) {
536 ; CHECK-LABEL: select_ororand:
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
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
549 %and = and i1 %c2, %c4
550 %or1 = or i1 %or, %and
551 %sel = select i1 %or1, i32 %w3, i32 0
555 define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) {
556 ; CHECK-LABEL: select_andor:
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
563 %c0 = icmp eq i32 %v1, %v2
564 %c1 = icmp sge i32 %v2, %v3
565 %c2 = icmp eq i32 %v1, 0
567 %and = and i1 %or, %c0
568 %sel = select i1 %and, i32 %v1, i32 %v2
572 define i32 @select_andor32(i32 %v1, i32 %v2, i32 %v3) {
573 ; SDISEL-LABEL: select_andor32:
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
582 ; GISEL-LABEL: select_andor32:
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
590 %c0 = icmp eq i32 %v1, %v2
591 %c1 = icmp sge i32 %v2, %v3
592 %c2 = icmp eq i32 %v1, 32
594 %and = and i1 %or, %c0
595 %sel = select i1 %and, i32 %v1, i32 %v2
599 define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
600 ; SDISEL-LABEL: select_noccmp1:
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
612 ; GISEL-LABEL: select_noccmp1:
614 ; GISEL-NEXT: mov x0, x3
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
629 define i64 @select_noccmp2(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
630 ; SDISEL-LABEL: select_noccmp2:
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]
642 ; GISEL-LABEL: select_noccmp2:
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]
652 %c0 = icmp slt i64 %v1, 0
653 %c1 = icmp sgt i64 %v1, 13
655 %sel = select i1 %or, i64 0, i64 %r
656 %ext = sext i1 %or to i32
657 store volatile i32 %ext, ptr @g
661 ; The following is not possible to implement with a single cmp;ccmp;csel
663 define i32 @select_noccmp3(i32 %v0, i32 %v1, i32 %v2) {
664 ; SDISEL-LABEL: select_noccmp3:
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
681 ; GISEL-LABEL: select_noccmp3:
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
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
706 ; Test the IR CCs that expand to two cond codes.
708 define 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:
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
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
723 define 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:
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
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
738 define 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:
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
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
753 define 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:
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
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
768 define 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:
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
776 %c0 = fcmp olt double %v0, %v1
777 %c1 = fcmp one double %v2, %v3
779 %sel = select i1 %cr, i32 %a, i32 %b
783 define 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:
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
791 %c0 = fcmp one double %v0, %v1
792 %c1 = fcmp olt double %v2, %v3
794 %sel = select i1 %cr, i32 %a, i32 %b
798 define 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:
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
806 %c0 = fcmp olt double %v0, %v1
807 %c1 = fcmp ueq double %v2, %v3
809 %sel = select i1 %cr, i32 %a, i32 %b
813 define 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:
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
821 %c0 = fcmp ueq double %v0, %v1
822 %c1 = fcmp olt double %v2, %v3
824 %sel = select i1 %cr, i32 %a, i32 %b
828 define 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:
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
837 %c0 = fcmp olt double %v0, %v1
838 %c1 = fcmp ogt double %v2, %v3
839 %c2 = fcmp ueq double %v4, %v5
842 %sel = select i1 %cr, i32 %a, i32 %b
846 define 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:
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
855 %c0 = fcmp olt double %v0, %v1
856 %c1 = fcmp ueq double %v2, %v3
857 %c2 = fcmp ogt double %v4, %v5
860 %sel = select i1 %cr, i32 %a, i32 %b
864 ; Verify that we correctly promote f16.
866 define 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:
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
878 ; GISEL-LABEL: half_select_and_olt_oge:
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
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
895 define 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:
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
908 ; GISEL-LABEL: half_select_and_olt_one:
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
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
926 ; Also verify that we don't try to generate f128 FCCMPs, using RT calls instead.
928 define 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:
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
953 ; GISEL-LABEL: f128_select_and_olt_oge:
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
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
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)
983 define i32 @deep_or(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
984 ; CHECK-LABEL: deep_or:
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
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
998 %and0 = and i1 %or, %c1
999 %and1 = and i1 %and0, %c0
1000 %sel = select i1 %and1, i32 %x, i32 %y
1004 ; Variation of deep_or, we still need to implement the OR first though.
1005 define i32 @deep_or1(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
1006 ; CHECK-LABEL: deep_or1:
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
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
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
1026 ; Variation of deep_or, we still need to implement the OR first though.
1027 define i32 @deep_or2(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
1028 ; CHECK-LABEL: deep_or2:
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
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
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
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.
1050 define 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
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
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)
1102 define 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
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
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)
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)
1168 declare i32 @callee(i32)
1170 define i1 @cmp_and_negative_const(i32 %0, i32 %1) {
1171 ; SDISEL-LABEL: cmp_and_negative_const:
1173 ; SDISEL-NEXT: cmn w0, #1
1174 ; SDISEL-NEXT: ccmn w1, #2, #0, eq
1175 ; SDISEL-NEXT: cset w0, eq
1178 ; GISEL-LABEL: cmp_and_negative_const:
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
1186 %3 = icmp eq i32 %0, -1
1187 %4 = icmp eq i32 %1, -2
1192 define i1 @cmp_or_negative_const(i32 %a, i32 %b) {
1193 ; SDISEL-LABEL: cmp_or_negative_const:
1195 ; SDISEL-NEXT: cmn w0, #1
1196 ; SDISEL-NEXT: ccmn w1, #2, #4, ne
1197 ; SDISEL-NEXT: cset w0, eq
1200 ; GISEL-LABEL: cmp_or_negative_const:
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
1208 %cmp = icmp eq i32 %a, -1
1209 %cmp1 = icmp eq i32 %b, -2
1210 %or.cond = or i1 %cmp, %cmp1
1213 attributes #0 = { nounwind }