[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / arm64-ccmp.ll
blob821f6e403a271335ecb5ce4a34e0a165cd414afb
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 ; SDISEL-LABEL: select_and:
461 ; SDISEL:       ; %bb.0:
462 ; SDISEL-NEXT:    cmp w1, #5
463 ; SDISEL-NEXT:    ccmp w0, w1, #0, ne
464 ; SDISEL-NEXT:    csel x0, x2, x3, lt
465 ; SDISEL-NEXT:    ret
467 ; GISEL-LABEL: select_and:
468 ; GISEL:       ; %bb.0:
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
473 ; GISEL-NEXT:    ret
474   %1 = icmp slt i32 %w0, %w1
475   %2 = icmp ne i32 5, %w1
476   %3 = and i1 %1, %2
477   %sel = select i1 %3, i64 %x2, i64 %x3
478   ret i64 %sel
481 define i64 @select_or(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
482 ; SDISEL-LABEL: select_or:
483 ; SDISEL:       ; %bb.0:
484 ; SDISEL-NEXT:    cmp w1, #5
485 ; SDISEL-NEXT:    ccmp w0, w1, #8, eq
486 ; SDISEL-NEXT:    csel x0, x2, x3, lt
487 ; SDISEL-NEXT:    ret
489 ; GISEL-LABEL: select_or:
490 ; GISEL:       ; %bb.0:
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
495 ; GISEL-NEXT:    ret
496   %1 = icmp slt i32 %w0, %w1
497   %2 = icmp ne i32 5, %w1
498   %3 = or i1 %1, %2
499   %sel = select i1 %3, i64 %x2, i64 %x3
500   ret i64 %sel
503 define float @select_or_float(i32 %w0, i32 %w1, float %x2, float %x3) {
504 ; SDISEL-LABEL: select_or_float:
505 ; SDISEL:       ; %bb.0:
506 ; SDISEL-NEXT:    cmp w1, #5
507 ; SDISEL-NEXT:    ccmp w0, w1, #8, eq
508 ; SDISEL-NEXT:    fcsel s0, s0, s1, lt
509 ; SDISEL-NEXT:    ret
511 ; GISEL-LABEL: select_or_float:
512 ; GISEL:       ; %bb.0:
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
517 ; GISEL-NEXT:    ret
518   %1 = icmp slt i32 %w0, %w1
519   %2 = icmp ne i32 5, %w1
520   %3 = or i1 %1, %2
521   %sel = select i1 %3, float %x2,float %x3
522   ret float %sel
525 define i64 @gccbug(i64 %x0, i64 %x1) {
526 ; SDISEL-LABEL: gccbug:
527 ; SDISEL:       ; %bb.0:
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
533 ; SDISEL-NEXT:    ret
535 ; GISEL-LABEL: gccbug:
536 ; GISEL:       ; %bb.0:
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
542 ; GISEL-NEXT:    ret
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
551   ret i64 %sel
554 define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) {
555 ; CHECK-LABEL: select_ororand:
556 ; CHECK:       ; %bb.0:
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
562 ; CHECK-NEXT:    ret
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
567   %or = or i1 %c0, %c1
568   %and = and i1 %c2, %c4
569   %or1 = or i1 %or, %and
570   %sel = select i1 %or1, i32 %w3, i32 0
571   ret i32 %sel
574 define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) {
575 ; CHECK-LABEL: select_andor:
576 ; CHECK:       ; %bb.0:
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
581 ; CHECK-NEXT:    ret
582   %c0 = icmp eq i32 %v1, %v2
583   %c1 = icmp sge i32 %v2, %v3
584   %c2 = icmp eq i32 %v1, 0
585   %or = or i1 %c2, %c1
586   %and = and i1 %or, %c0
587   %sel = select i1 %and, i32 %v1, i32 %v2
588   ret i32 %sel
591 define i32 @select_andor32(i32 %v1, i32 %v2, i32 %v3) {
592 ; SDISEL-LABEL: select_andor32:
593 ; SDISEL:       ; %bb.0:
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
599 ; SDISEL-NEXT:    ret
601 ; GISEL-LABEL: select_andor32:
602 ; GISEL:       ; %bb.0:
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
608 ; GISEL-NEXT:    ret
609   %c0 = icmp eq i32 %v1, %v2
610   %c1 = icmp sge i32 %v2, %v3
611   %c2 = icmp eq i32 %v1, 32
612   %or = or i1 %c2, %c1
613   %and = and i1 %or, %c0
614   %sel = select i1 %and, i32 %v1, i32 %v2
615   ret i32 %sel
618 define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
619 ; SDISEL-LABEL: select_noccmp1:
620 ; SDISEL:       ; %bb.0:
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
629 ; SDISEL-NEXT:    ret
631 ; GISEL-LABEL: select_noccmp1:
632 ; GISEL:       ; %bb.0:
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
646 ; GISEL-NEXT:    ret
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
655   ret i64 %sel
658 @g = global i32 0
660 define i64 @select_noccmp2(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
661 ; SDISEL-LABEL: select_noccmp2:
662 ; SDISEL:       ; %bb.0:
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]
671 ; SDISEL-NEXT:    ret
673 ; GISEL-LABEL: select_noccmp2:
674 ; GISEL:       ; %bb.0:
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]
685 ; GISEL-NEXT:    ret
686   %c0 = icmp slt i64 %v1, 0
687   %c1 = icmp sgt i64 %v1, 13
688   %or = or i1 %c0, %c1
689   %sel = select i1 %or, i64 0, i64 %r
690   %ext = sext i1 %or to i32
691   store volatile i32 %ext, ptr @g
692   ret i64 %sel
695 ; The following is not possible to implement with a single cmp;ccmp;csel
696 ; sequence.
697 define i32 @select_noccmp3(i32 %v0, i32 %v1, i32 %v2) {
698 ; SDISEL-LABEL: select_noccmp3:
699 ; SDISEL:       ; %bb.0:
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
713 ; SDISEL-NEXT:    ret
715 ; GISEL-LABEL: select_noccmp3:
716 ; GISEL:       ; %bb.0:
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
736 ; GISEL-NEXT:    ret
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
749   ret i32 %sel
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:
756 ; CHECK:       ; %bb.0:
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
761 ; CHECK-NEXT:    ret
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
766   ret i32 %sel
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:
771 ; CHECK:       ; %bb.0:
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
776 ; CHECK-NEXT:    ret
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
781   ret i32 %sel
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:
786 ; CHECK:       ; %bb.0:
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
791 ; CHECK-NEXT:    ret
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
796   ret i32 %sel
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:
801 ; CHECK:       ; %bb.0:
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
806 ; CHECK-NEXT:    ret
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
811   ret i32 %sel
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:
816 ; CHECK:       ; %bb.0:
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
821 ; CHECK-NEXT:    ret
822   %c0 = fcmp olt double %v0, %v1
823   %c1 = fcmp one double %v2, %v3
824   %cr = or i1 %c1, %c0
825   %sel = select i1 %cr, i32 %a, i32 %b
826   ret i32 %sel
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:
831 ; CHECK:       ; %bb.0:
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
836 ; CHECK-NEXT:    ret
837   %c0 = fcmp one double %v0, %v1
838   %c1 = fcmp olt double %v2, %v3
839   %cr = or i1 %c1, %c0
840   %sel = select i1 %cr, i32 %a, i32 %b
841   ret i32 %sel
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:
846 ; CHECK:       ; %bb.0:
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
851 ; CHECK-NEXT:    ret
852   %c0 = fcmp olt double %v0, %v1
853   %c1 = fcmp ueq double %v2, %v3
854   %cr = or i1 %c1, %c0
855   %sel = select i1 %cr, i32 %a, i32 %b
856   ret i32 %sel
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:
861 ; CHECK:       ; %bb.0:
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
866 ; CHECK-NEXT:    ret
867   %c0 = fcmp ueq double %v0, %v1
868   %c1 = fcmp olt double %v2, %v3
869   %cr = or i1 %c1, %c0
870   %sel = select i1 %cr, i32 %a, i32 %b
871   ret i32 %sel
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:
876 ; CHECK:       ; %bb.0:
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
882 ; CHECK-NEXT:    ret
883   %c0 = fcmp olt double %v0, %v1
884   %c1 = fcmp ogt double %v2, %v3
885   %c2 = fcmp ueq double %v4, %v5
886   %c3 = or i1 %c1, %c0
887   %cr = or i1 %c2, %c3
888   %sel = select i1 %cr, i32 %a, i32 %b
889   ret i32 %sel
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:
894 ; CHECK:       ; %bb.0:
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
900 ; CHECK-NEXT:    ret
901   %c0 = fcmp olt double %v0, %v1
902   %c1 = fcmp ueq double %v2, %v3
903   %c2 = fcmp ogt double %v4, %v5
904   %c3 = or i1 %c1, %c0
905   %cr = or i1 %c2, %c3
906   %sel = select i1 %cr, i32 %a, i32 %b
907   ret i32 %sel
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:
914 ; SDISEL:       ; %bb.0:
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
922 ; SDISEL-NEXT:    ret
924 ; GISEL-LABEL: half_select_and_olt_oge:
925 ; GISEL:       ; %bb.0:
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
933 ; GISEL-NEXT:    ret
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
938   ret i32 %sel
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:
943 ; SDISEL:       ; %bb.0:
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
952 ; SDISEL-NEXT:    ret
954 ; GISEL-LABEL: half_select_and_olt_one:
955 ; GISEL:       ; %bb.0:
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
964 ; GISEL-NEXT:    ret
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
969   ret i32 %sel
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:
976 ; CHECK:       ; %bb.0:
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
997 ; CHECK-NEXT:    ret
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
1002   ret i32 %sel
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:
1009 ; CHECK:       ; %bb.0:
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
1015 ; CHECK-NEXT:    ret
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
1025   ret i32 %sel
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:
1031 ; CHECK:       ; %bb.0:
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
1037 ; CHECK-NEXT:    ret
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
1047   ret i32 %sel
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:
1053 ; CHECK:       ; %bb.0:
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
1059 ; CHECK-NEXT:    ret
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
1069   ret i32 %sel
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
1094 ; SDISEL-NEXT:    ret
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
1114 ; GISEL-NEXT:    ret
1115 entry:
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)
1123   ret i32 %p
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
1150 ; SDISEL-NEXT:    ret
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
1177 ; GISEL-NEXT:    ret
1178 entry:
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)
1190   ret i32 %p
1192 declare i32 @callee(i32)
1194 define i1 @cmp_and_negative_const(i32 %0, i32 %1) {
1195 ; SDISEL-LABEL: cmp_and_negative_const:
1196 ; SDISEL:       ; %bb.0:
1197 ; SDISEL-NEXT:    cmn w0, #1
1198 ; SDISEL-NEXT:    ccmn w1, #2, #0, eq
1199 ; SDISEL-NEXT:    cset w0, eq
1200 ; SDISEL-NEXT:    ret
1202 ; GISEL-LABEL: cmp_and_negative_const:
1203 ; GISEL:       ; %bb.0:
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
1209 ; GISEL-NEXT:    ret
1210   %3 = icmp eq i32 %0, -1
1211   %4 = icmp eq i32 %1, -2
1212   %5 = and i1 %3, %4
1213   ret i1 %5
1216 define i1 @cmp_or_negative_const(i32 %a, i32 %b) {
1217 ; SDISEL-LABEL: cmp_or_negative_const:
1218 ; SDISEL:       ; %bb.0:
1219 ; SDISEL-NEXT:    cmn w0, #1
1220 ; SDISEL-NEXT:    ccmn w1, #2, #4, ne
1221 ; SDISEL-NEXT:    cset w0, eq
1222 ; SDISEL-NEXT:    ret
1224 ; GISEL-LABEL: cmp_or_negative_const:
1225 ; GISEL:       ; %bb.0:
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
1231 ; GISEL-NEXT:    ret
1232   %cmp = icmp eq i32 %a, -1
1233   %cmp1 = icmp eq i32 %b, -2
1234   %or.cond = or i1 %cmp, %cmp1
1235   ret i1 %or.cond
1237 attributes #0 = { nounwind }