[Instrumentation] Fix a warning
[llvm-project.git] / llvm / test / CodeGen / AArch64 / arm64-ccmp.ll
blob06e957fdcc6a2af4db3e00eaaa9af1af617b409e
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
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
19 entry:
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
25 if.then:
26   %call = tail call i32 @foo() nounwind
27   br label %if.end
29 if.end:
30   ret i32 7
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
46 ; SDISEL-NEXT:    ret
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
60 entry:
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
66 if.then:
67   %call = tail call i32 @foo() nounwind
68   br label %if.end
70 if.end:
71   ret i32 7
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
92 ; SDISEL-NEXT:    ret
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
111 entry:
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
125   br label %if.end
127 if.end:                                           ; preds = %if.then, %lor.lhs.false
128   ret i32 7
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
148 ; CHECK-NEXT:    ret
149 entry:
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
164   br label %if.end
166 if.end:                                           ; preds = %if.then, %lor.lhs.false
167   ret i32 7
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.
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
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
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
205 entry:
206   %cmp = icmp sgt i32 %a, 0
207   br i1 %cmp, label %land.lhs.true, label %if.end
209 land.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
214 if.then:
215   %call = tail call i32 @foo() nounwind
216   br label %if.end
218 if.end:
219   ret i32 7
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
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
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
259 entry:
260   %cmp = icmp sgt i32 %a, 0
261   br i1 %cmp, label %land.lhs.true, label %if.end
263 land.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
269 if.then:
270   %call = tail call i32 @foo() nounwind
271   br label %if.end
273 if.end:
274   ret i32 7
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
287 ; CHECK-NEXT:    ret
288 ; CHECK-NEXT:  LBB6_2: ; %if.then
289 ; CHECK-NEXT:    b _foo
290 entry:
291   %cmp = icmp sgt i32 %a, %b
292   br i1 %cmp, label %land.lhs.true, label %if.end
294 land.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
301 if.then:
302   %call = tail call i32 @foo() nounwind
303   br label %if.end
305 if.end:
306   ret void
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
322 ; CHECK-NEXT:    ret
323 entry:
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
329 if.then:
330   %call = tail call i32 @foo() nounwind
331   br label %if.end
333 if.end:
334   ret i32 7
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
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
357 entry:
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
363 if.then:
364   %call = tail call i32 @foo() nounwind
365   br label %if.end
367 if.end:
368   ret i32 7
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
384 ; CHECK-NEXT:    ret
385 entry:
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
391 if.then:
392   %call = tail call i32 @foo() nounwind
393   br label %if.end
395 if.end:
396   ret i32 7
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
412 ; CHECK-NEXT:    ret
413 entry:
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
419 if.then:
420   %call = tail call i32 @foo() nounwind
421   br label %if.end
423 if.end:
424   ret i32 7
426 declare i32 @foo()
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
436 ; CHECK-NEXT:    ret
437 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
446   ]
448 if.end85:
449   ret void
451 sw.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
459 define 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
473 define 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
487 define 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
501 define 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
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
528   %or = or i1 %cmp2, %cmp1
529   %and = and i1 %or, %cmp0
531   %sel = select i1 %and, i64 2, i64 1
532   ret i64 %sel
535 define 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
555 define 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
572 define 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
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
599 define 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
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
627 @g = global i32 0
629 define 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
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
661 ; The following is not possible to implement with a single cmp;ccmp;csel
662 ; sequence.
663 define 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
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
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:
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
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:
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
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:
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
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:
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
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:
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
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:
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
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:
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
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:
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
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:
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
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:
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
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:
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
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
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:
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
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
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:
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
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
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:
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
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
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:
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
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
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:
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
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
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
1070 ; SDISEL-NEXT:    ret
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
1091 entry:
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
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
1126 ; SDISEL-NEXT:    ret
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
1154 entry:
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)
1166   ret i32 %p
1168 declare i32 @callee(i32)
1170 define 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
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
1192 define 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
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
1213 attributes #0 = { nounwind }