Revert 374373: [Codegen] Alter the default promotion for saturating adds and subs
[llvm-core.git] / test / CodeGen / AArch64 / arm64-ccmp.ll
blob88a512e089795422976693082006281d6e6b7960
1 ; RUN: llc < %s -mcpu=cyclone -verify-machineinstrs -aarch64-enable-ccmp -aarch64-stress-ccmp | FileCheck %s
2 target triple = "arm64-apple-ios"
4 ; CHECK: single_same
5 ; CHECK: cmp w0, #5
6 ; CHECK-NEXT: ccmp w1, #17, #4, ne
7 ; CHECK-NEXT: b.ne
8 ; CHECK: %if.then
9 ; CHECK: bl _foo
10 ; CHECK: %if.end
11 define i32 @single_same(i32 %a, i32 %b) nounwind ssp {
12 entry:
13   %cmp = icmp eq i32 %a, 5
14   %cmp1 = icmp eq i32 %b, 17
15   %or.cond = or i1 %cmp, %cmp1
16   br i1 %or.cond, label %if.then, label %if.end
18 if.then:
19   %call = tail call i32 @foo() nounwind
20   br label %if.end
22 if.end:
23   ret i32 7
26 ; Different condition codes for the two compares.
27 ; CHECK: single_different
28 ; CHECK: cmp w0, #6
29 ; CHECK-NEXT: ccmp w1, #17, #0, ge
30 ; CHECK-NEXT: b.eq
31 ; CHECK: %if.then
32 ; CHECK: bl _foo
33 ; CHECK: %if.end
34 define i32 @single_different(i32 %a, i32 %b) nounwind ssp {
35 entry:
36   %cmp = icmp sle i32 %a, 5
37   %cmp1 = icmp ne i32 %b, 17
38   %or.cond = or i1 %cmp, %cmp1
39   br i1 %or.cond, label %if.then, label %if.end
41 if.then:
42   %call = tail call i32 @foo() nounwind
43   br label %if.end
45 if.end:
46   ret i32 7
49 ; Second block clobbers the flags, can't convert (easily).
50 ; CHECK: single_flagclobber
51 ; CHECK: cmp
52 ; CHECK: b.eq
53 ; CHECK: cmp
54 ; CHECK: b.gt
55 define i32 @single_flagclobber(i32 %a, i32 %b) nounwind ssp {
56 entry:
57   %cmp = icmp eq i32 %a, 5
58   br i1 %cmp, label %if.then, label %lor.lhs.false
60 lor.lhs.false:                                    ; preds = %entry
61   %cmp1 = icmp slt i32 %b, 7
62   %mul = shl nsw i32 %b, 1
63   %add = add nsw i32 %b, 1
64   %cond = select i1 %cmp1, i32 %mul, i32 %add
65   %cmp2 = icmp slt i32 %cond, 17
66   br i1 %cmp2, label %if.then, label %if.end
68 if.then:                                          ; preds = %lor.lhs.false, %entry
69   %call = tail call i32 @foo() nounwind
70   br label %if.end
72 if.end:                                           ; preds = %if.then, %lor.lhs.false
73   ret i32 7
76 ; Second block clobbers the flags and ends with a tbz terminator.
77 ; CHECK: single_flagclobber_tbz
78 ; CHECK: cmp
79 ; CHECK: b.eq
80 ; CHECK: cmp
81 ; CHECK: tbz
82 define i32 @single_flagclobber_tbz(i32 %a, i32 %b) nounwind ssp {
83 entry:
84   %cmp = icmp eq i32 %a, 5
85   br i1 %cmp, label %if.then, label %lor.lhs.false
87 lor.lhs.false:                                    ; preds = %entry
88   %cmp1 = icmp slt i32 %b, 7
89   %mul = shl nsw i32 %b, 1
90   %add = add nsw i32 %b, 1
91   %cond = select i1 %cmp1, i32 %mul, i32 %add
92   %and = and i32 %cond, 8
93   %cmp2 = icmp ne i32 %and, 0
94   br i1 %cmp2, label %if.then, label %if.end
96 if.then:                                          ; preds = %lor.lhs.false, %entry
97   %call = tail call i32 @foo() nounwind
98   br label %if.end
100 if.end:                                           ; preds = %if.then, %lor.lhs.false
101   ret i32 7
104 ; Speculatively execute division by zero.
105 ; The sdiv/udiv instructions do not trap when the divisor is zero, so they are
106 ; safe to speculate.
107 ; CHECK-LABEL: speculate_division:
108 ; CHECK: cmp w0, #1
109 ; CHECK: sdiv [[DIVRES:w[0-9]+]], w1, w0
110 ; CHECK: ccmp [[DIVRES]], #16, #0, ge
111 ; CHECK: b.le [[BLOCK:LBB[0-9_]+]]
112 ; CHECK: [[BLOCK]]:
113 ; CHECK: bl _foo
114 ; CHECK: mov w0, #7
115 define i32 @speculate_division(i32 %a, i32 %b) nounwind ssp {
116 entry:
117   %cmp = icmp sgt i32 %a, 0
118   br i1 %cmp, label %land.lhs.true, label %if.end
120 land.lhs.true:
121   %div = sdiv i32 %b, %a
122   %cmp1 = icmp slt i32 %div, 17
123   br i1 %cmp1, label %if.then, label %if.end
125 if.then:
126   %call = tail call i32 @foo() nounwind
127   br label %if.end
129 if.end:
130   ret i32 7
133 ; Floating point compare.
134 ; CHECK: single_fcmp
135 ; CHECK: ; %bb.
136 ; CHECK: cmp
137 ; CHECK-NOT: b.
138 ; CHECK: fccmp {{.*}}, #8, ge
139 ; CHECK: b.ge
140 define i32 @single_fcmp(i32 %a, float %b) nounwind ssp {
141 entry:
142   %cmp = icmp sgt i32 %a, 0
143   br i1 %cmp, label %land.lhs.true, label %if.end
145 land.lhs.true:
146   %conv = sitofp i32 %a to float
147   %div = fdiv float %b, %conv
148   %cmp1 = fcmp oge float %div, 1.700000e+01
149   br i1 %cmp1, label %if.then, label %if.end
151 if.then:
152   %call = tail call i32 @foo() nounwind
153   br label %if.end
155 if.end:
156   ret i32 7
159 ; Chain multiple compares.
160 ; CHECK: multi_different
161 ; CHECK: cmp
162 ; CHECK: ccmp
163 ; CHECK: ccmp
164 ; CHECK: b.
165 define void @multi_different(i32 %a, i32 %b, i32 %c) nounwind ssp {
166 entry:
167   %cmp = icmp sgt i32 %a, %b
168   br i1 %cmp, label %land.lhs.true, label %if.end
170 land.lhs.true:
171   %div = sdiv i32 %b, %a
172   %cmp1 = icmp eq i32 %div, 5
173   %cmp4 = icmp sgt i32 %div, %c
174   %or.cond = and i1 %cmp1, %cmp4
175   br i1 %or.cond, label %if.then, label %if.end
177 if.then:
178   %call = tail call i32 @foo() nounwind
179   br label %if.end
181 if.end:
182   ret void
185 ; Convert a cbz in the head block.
186 ; CHECK: cbz_head
187 ; CHECK: cmp w0, #0
188 ; CHECK: ccmp
189 define i32 @cbz_head(i32 %a, i32 %b) nounwind ssp {
190 entry:
191   %cmp = icmp eq i32 %a, 0
192   %cmp1 = icmp ne i32 %b, 17
193   %or.cond = or i1 %cmp, %cmp1
194   br i1 %or.cond, label %if.then, label %if.end
196 if.then:
197   %call = tail call i32 @foo() nounwind
198   br label %if.end
200 if.end:
201   ret i32 7
204 ; Check that the immediate operand is in range. The ccmp instruction encodes a
205 ; smaller range of immediates than subs/adds.
206 ; The ccmp immediates must be in the range 0-31.
207 ; CHECK: immediate_range
208 ; CHECK-NOT: ccmp
209 define i32 @immediate_range(i32 %a, i32 %b) nounwind ssp {
210 entry:
211   %cmp = icmp eq i32 %a, 5
212   %cmp1 = icmp eq i32 %b, 32
213   %or.cond = or i1 %cmp, %cmp1
214   br i1 %or.cond, label %if.then, label %if.end
216 if.then:
217   %call = tail call i32 @foo() nounwind
218   br label %if.end
220 if.end:
221   ret i32 7
224 ; Convert a cbz in the second block.
225 ; CHECK: cbz_second
226 ; CHECK: cmp w0, #0
227 ; CHECK: ccmp w1, #0, #0, ne
228 ; CHECK: b.eq
229 define i32 @cbz_second(i32 %a, i32 %b) nounwind ssp {
230 entry:
231   %cmp = icmp eq i32 %a, 0
232   %cmp1 = icmp ne i32 %b, 0
233   %or.cond = or i1 %cmp, %cmp1
234   br i1 %or.cond, label %if.then, label %if.end
236 if.then:
237   %call = tail call i32 @foo() nounwind
238   br label %if.end
240 if.end:
241   ret i32 7
244 ; Convert a cbnz in the second block.
245 ; CHECK: cbnz_second
246 ; CHECK: cmp w0, #0
247 ; CHECK: ccmp w1, #0, #4, ne
248 ; CHECK: b.ne
249 define i32 @cbnz_second(i32 %a, i32 %b) nounwind ssp {
250 entry:
251   %cmp = icmp eq i32 %a, 0
252   %cmp1 = icmp eq i32 %b, 0
253   %or.cond = or i1 %cmp, %cmp1
254   br i1 %or.cond, label %if.then, label %if.end
256 if.then:
257   %call = tail call i32 @foo() nounwind
258   br label %if.end
260 if.end:
261   ret i32 7
263 declare i32 @foo()
265 %str1 = type { %str2 }
266 %str2 = type { [24 x i8], i8*, i32, %str1*, i32, [4 x i8], %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, i8*, i8, i8*, %str1*, i8* }
268 ; Test case distilled from 126.gcc.
269 ; The phi in sw.bb.i.i gets multiple operands for the %entry predecessor.
270 ; CHECK: build_modify_expr
271 define void @build_modify_expr() nounwind ssp {
272 entry:
273   switch i32 undef, label %sw.bb.i.i [
274     i32 69, label %if.end85
275     i32 70, label %if.end85
276     i32 71, label %if.end85
277     i32 72, label %if.end85
278     i32 73, label %if.end85
279     i32 105, label %if.end85
280     i32 106, label %if.end85
281   ]
283 if.end85:
284   ret void
286 sw.bb.i.i:
287   %ref.tr.i.i = phi %str1* [ %0, %sw.bb.i.i ], [ undef, %entry ]
288   %operands.i.i = getelementptr inbounds %str1, %str1* %ref.tr.i.i, i64 0, i32 0, i32 2
289   %arrayidx.i.i = bitcast i32* %operands.i.i to %str1**
290   %0 = load %str1*, %str1** %arrayidx.i.i, align 8
291   %code1.i.i.phi.trans.insert = getelementptr inbounds %str1, %str1* %0, i64 0, i32 0, i32 0, i64 16
292   br label %sw.bb.i.i
295 ; CHECK-LABEL: select_and
296 define i64 @select_and(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
297 ; CHECK: cmp w1, #5
298 ; CHECK-NEXT: ccmp w0, w1, #0, ne
299 ; CHECK-NEXT: csel x0, x2, x3, lt
300 ; CHECK-NEXT: ret
301   %1 = icmp slt i32 %w0, %w1
302   %2 = icmp ne i32 5, %w1
303   %3 = and i1 %1, %2
304   %sel = select i1 %3, i64 %x2, i64 %x3
305   ret i64 %sel
308 ; CHECK-LABEL: select_or
309 define i64 @select_or(i32 %w0, i32 %w1, i64 %x2, i64 %x3) {
310 ; CHECK: cmp w1, #5
311 ; CHECK-NEXT: ccmp w0, w1, #8, eq
312 ; CHECK-NEXT: csel x0, x2, x3, lt
313 ; CHECK-NEXT: ret
314   %1 = icmp slt i32 %w0, %w1
315   %2 = icmp ne i32 5, %w1
316   %3 = or i1 %1, %2
317   %sel = select i1 %3, i64 %x2, i64 %x3
318   ret i64 %sel
321 ; CHECK-LABEL: gccbug
322 define i64 @gccbug(i64 %x0, i64 %x1) {
323 ; CHECK: cmp x0, #2
324 ; CHECK-NEXT: ccmp x0, #4, #4, ne
325 ; CHECK-NEXT: ccmp x1, #0, #0, eq
326 ; CHECK-NEXT: mov w[[REGNUM:[0-9]+]], #1
327 ; CHECK-NEXT: cinc x0, x[[REGNUM]], eq
328 ; CHECK-NEXT: ret
329   %cmp0 = icmp eq i64 %x1, 0
330   %cmp1 = icmp eq i64 %x0, 2
331   %cmp2 = icmp eq i64 %x0, 4
333   %or = or i1 %cmp2, %cmp1
334   %and = and i1 %or, %cmp0
336   %sel = select i1 %and, i64 2, i64 1
337   ret i64 %sel
340 ; CHECK-LABEL: select_ororand
341 define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) {
342 ; CHECK: cmp w3, #4
343 ; CHECK-NEXT: ccmp w2, #2, #0, gt
344 ; CHECK-NEXT: ccmp w1, #13, #2, ge
345 ; CHECK-NEXT: ccmp w0, #0, #4, ls
346 ; CHECK-NEXT: csel w0, w3, wzr, eq
347 ; CHECK-NEXT: ret
348   %c0 = icmp eq i32 %w0, 0
349   %c1 = icmp ugt i32 %w1, 13
350   %c2 = icmp slt i32 %w2, 2
351   %c4 = icmp sgt i32 %w3, 4
352   %or = or i1 %c0, %c1
353   %and = and i1 %c2, %c4
354   %or1 = or i1 %or, %and
355   %sel = select i1 %or1, i32 %w3, i32 0
356   ret i32 %sel
359 ; CHECK-LABEL: select_andor
360 define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) {
361 ; CHECK: cmp w1, w2
362 ; CHECK-NEXT: ccmp w0, #0, #4, lt
363 ; CHECK-NEXT: ccmp w0, w1, #0, eq
364 ; CHECK-NEXT: csel w0, w0, w1, eq
365 ; CHECK-NEXT: ret
366   %c0 = icmp eq i32 %v1, %v2
367   %c1 = icmp sge i32 %v2, %v3
368   %c2 = icmp eq i32 %v1, 0
369   %or = or i1 %c2, %c1
370   %and = and i1 %or, %c0
371   %sel = select i1 %and, i32 %v1, i32 %v2
372   ret i32 %sel
375 ; CHECK-LABEL: select_noccmp1
376 define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
377 ; CHECK: cmp x0, #0
378 ; CHECK-NEXT: cset [[REG0:w[0-9]+]], lt
379 ; CHECK-NEXT: cmp x0, #13
380 ; CHECK-NOT: ccmp
381 ; CHECK-NEXT: cset [[REG1:w[0-9]+]], gt
382 ; CHECK-NEXT: cmp x2, #2
383 ; CHECK-NEXT: cset [[REG2:w[0-9]+]], lt
384 ; CHECK-NEXT: cmp x2, #4
385 ; CHECK-NEXT: cset [[REG3:w[0-9]+]], gt
386 ; CHECK-NEXT: and [[REG4:w[0-9]+]], [[REG0]], [[REG1]]
387 ; CHECK-NEXT: and [[REG5:w[0-9]+]], [[REG2]], [[REG3]]
388 ; CHECK-NEXT: orr [[REG6:w[0-9]+]], [[REG4]], [[REG5]]
389 ; CHECK-NEXT: cmp [[REG6]], #0
390 ; CHECK-NEXT: csel x0, xzr, x3, ne
391 ; CHECK-NEXT: ret
392   %c0 = icmp slt i64 %v1, 0
393   %c1 = icmp sgt i64 %v1, 13
394   %c2 = icmp slt i64 %v3, 2
395   %c4 = icmp sgt i64 %v3, 4
396   %and0 = and i1 %c0, %c1
397   %and1 = and i1 %c2, %c4
398   %or = or i1 %and0, %and1
399   %sel = select i1 %or, i64 0, i64 %r
400   ret i64 %sel
403 @g = global i32 0
405 ; Should not use ccmp if we have to compute the or expression in an integer
406 ; register anyway because of other users.
407 ; CHECK-LABEL: select_noccmp2
408 define i64 @select_noccmp2(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
409 ; CHECK: cmp x0, #0
410 ; CHECK-NEXT: cset [[REG0:w[0-9]+]], lt
411 ; CHECK-NOT: ccmp
412 ; CHECK-NEXT: cmp x0, #13
413 ; CHECK-NEXT: cset [[REG1:w[0-9]+]], gt
414 ; CHECK-NEXT: orr [[REG2:w[0-9]+]], [[REG0]], [[REG1]]
415 ; CHECK-NEXT: cmp [[REG2]], #0
416 ; CHECK-NEXT: csel x0, xzr, x3, ne
417 ; CHECK-NEXT: sbfx [[REG3:w[0-9]+]], [[REG2]], #0, #1
418 ; CHECK-NEXT: adrp x[[REGN4:[0-9]+]], _g@PAGE
419 ; CHECK-NEXT: str [[REG3]], [x[[REGN4]], _g@PAGEOFF]
420 ; CHECK-NEXT: ret
421   %c0 = icmp slt i64 %v1, 0
422   %c1 = icmp sgt i64 %v1, 13
423   %or = or i1 %c0, %c1
424   %sel = select i1 %or, i64 0, i64 %r
425   %ext = sext i1 %or to i32
426   store volatile i32 %ext, i32* @g
427   ret i64 %sel
430 ; The following is not possible to implement with a single cmp;ccmp;csel
431 ; sequence.
432 ; CHECK-LABEL: select_noccmp3
433 define i32 @select_noccmp3(i32 %v0, i32 %v1, i32 %v2) {
434   %c0 = icmp slt i32 %v0, 0
435   %c1 = icmp sgt i32 %v0, 13
436   %c2 = icmp slt i32 %v0, 22
437   %c3 = icmp sgt i32 %v0, 44
438   %c4 = icmp eq i32 %v0, 99
439   %c5 = icmp eq i32 %v0, 77
440   %or0 = or i1 %c0, %c1
441   %or1 = or i1 %c2, %c3
442   %and0 = and i1 %or0, %or1
443   %or2 = or i1 %c4, %c5
444   %and1 = and i1 %and0, %or2
445   %sel = select i1 %and1, i32 %v1, i32 %v2
446   ret i32 %sel
449 ; Test the IR CCs that expand to two cond codes.
451 ; CHECK-LABEL: select_and_olt_one:
452 ; CHECK-LABEL: ; %bb.0:
453 ; CHECK-NEXT: fcmp d0, d1
454 ; CHECK-NEXT: fccmp d2, d3, #4, mi
455 ; CHECK-NEXT: fccmp d2, d3, #1, ne
456 ; CHECK-NEXT: csel w0, w0, w1, vc
457 ; CHECK-NEXT: ret
458 define i32 @select_and_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
459   %c0 = fcmp olt double %v0, %v1
460   %c1 = fcmp one double %v2, %v3
461   %cr = and i1 %c1, %c0
462   %sel = select i1 %cr, i32 %a, i32 %b
463   ret i32 %sel
466 ; CHECK-LABEL: select_and_one_olt:
467 ; CHECK-LABEL: ; %bb.0:
468 ; CHECK-NEXT: fcmp d0, d1
469 ; CHECK-NEXT: fccmp d0, d1, #1, ne
470 ; CHECK-NEXT: fccmp d2, d3, #0, vc
471 ; CHECK-NEXT: csel w0, w0, w1, mi
472 ; CHECK-NEXT: ret
473 define i32 @select_and_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
474   %c0 = fcmp one double %v0, %v1
475   %c1 = fcmp olt double %v2, %v3
476   %cr = and i1 %c1, %c0
477   %sel = select i1 %cr, i32 %a, i32 %b
478   ret i32 %sel
481 ; CHECK-LABEL: select_and_olt_ueq:
482 ; CHECK-LABEL: ; %bb.0:
483 ; CHECK-NEXT: fcmp d0, d1
484 ; CHECK-NEXT: fccmp d2, d3, #0, mi
485 ; CHECK-NEXT: fccmp d2, d3, #8, le
486 ; CHECK-NEXT: csel w0, w0, w1, pl
487 ; CHECK-NEXT: ret
488 define i32 @select_and_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
489   %c0 = fcmp olt double %v0, %v1
490   %c1 = fcmp ueq double %v2, %v3
491   %cr = and i1 %c1, %c0
492   %sel = select i1 %cr, i32 %a, i32 %b
493   ret i32 %sel
496 ; CHECK-LABEL: select_and_ueq_olt:
497 ; CHECK-LABEL: ; %bb.0:
498 ; CHECK-NEXT: fcmp d0, d1
499 ; CHECK-NEXT: fccmp d0, d1, #8, le
500 ; CHECK-NEXT: fccmp d2, d3, #0, pl
501 ; CHECK-NEXT: csel w0, w0, w1, mi
502 ; CHECK-NEXT: ret
503 define i32 @select_and_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
504   %c0 = fcmp ueq double %v0, %v1
505   %c1 = fcmp olt double %v2, %v3
506   %cr = and i1 %c1, %c0
507   %sel = select i1 %cr, i32 %a, i32 %b
508   ret i32 %sel
511 ; CHECK-LABEL: select_or_olt_one:
512 ; CHECK-LABEL: ; %bb.0:
513 ; CHECK-NEXT: fcmp d0, d1
514 ; CHECK-NEXT: fccmp d2, d3, #0, pl
515 ; CHECK-NEXT: fccmp d2, d3, #8, le
516 ; CHECK-NEXT: csel w0, w0, w1, mi
517 ; CHECK-NEXT: ret
518 define i32 @select_or_olt_one(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
519   %c0 = fcmp olt double %v0, %v1
520   %c1 = fcmp one double %v2, %v3
521   %cr = or i1 %c1, %c0
522   %sel = select i1 %cr, i32 %a, i32 %b
523   ret i32 %sel
526 ; CHECK-LABEL: select_or_one_olt:
527 ; CHECK-LABEL: ; %bb.0:
528 ; CHECK-NEXT: fcmp d0, d1
529 ; CHECK-NEXT: fccmp d0, d1, #8, le
530 ; CHECK-NEXT: fccmp d2, d3, #8, pl
531 ; CHECK-NEXT: csel w0, w0, w1, mi
532 ; CHECK-NEXT: ret
533 define i32 @select_or_one_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
534   %c0 = fcmp one double %v0, %v1
535   %c1 = fcmp olt double %v2, %v3
536   %cr = or i1 %c1, %c0
537   %sel = select i1 %cr, i32 %a, i32 %b
538   ret i32 %sel
541 ; CHECK-LABEL: select_or_olt_ueq:
542 ; CHECK-LABEL: ; %bb.0:
543 ; CHECK-NEXT: fcmp d0, d1
544 ; CHECK-NEXT: fccmp d2, d3, #4, pl
545 ; CHECK-NEXT: fccmp d2, d3, #1, ne
546 ; CHECK-NEXT: csel w0, w0, w1, vs
547 ; CHECK-NEXT: ret
548 define i32 @select_or_olt_ueq(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
549   %c0 = fcmp olt double %v0, %v1
550   %c1 = fcmp ueq double %v2, %v3
551   %cr = or i1 %c1, %c0
552   %sel = select i1 %cr, i32 %a, i32 %b
553   ret i32 %sel
556 ; CHECK-LABEL: select_or_ueq_olt:
557 ; CHECK-LABEL: ; %bb.0:
558 ; CHECK-NEXT: fcmp d0, d1
559 ; CHECK-NEXT: fccmp d0, d1, #1, ne
560 ; CHECK-NEXT: fccmp d2, d3, #8, vc
561 ; CHECK-NEXT: csel w0, w0, w1, mi
562 ; CHECK-NEXT: ret
563 define i32 @select_or_ueq_olt(double %v0, double %v1, double %v2, double %v3, i32 %a, i32 %b) #0 {
564   %c0 = fcmp ueq double %v0, %v1
565   %c1 = fcmp olt double %v2, %v3
566   %cr = or i1 %c1, %c0
567   %sel = select i1 %cr, i32 %a, i32 %b
568   ret i32 %sel
571 ; CHECK-LABEL: select_or_olt_ogt_ueq:
572 ; CHECK-LABEL: ; %bb.0:
573 ; CHECK-NEXT: fcmp d0, d1
574 ; CHECK-NEXT: fccmp d2, d3, #0, pl
575 ; CHECK-NEXT: fccmp d4, d5, #4, le
576 ; CHECK-NEXT: fccmp d4, d5, #1, ne
577 ; CHECK-NEXT: csel w0, w0, w1, vs
578 ; CHECK-NEXT: ret
579 define i32 @select_or_olt_ogt_ueq(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 {
580   %c0 = fcmp olt double %v0, %v1
581   %c1 = fcmp ogt double %v2, %v3
582   %c2 = fcmp ueq double %v4, %v5
583   %c3 = or i1 %c1, %c0
584   %cr = or i1 %c2, %c3
585   %sel = select i1 %cr, i32 %a, i32 %b
586   ret i32 %sel
589 ; CHECK-LABEL: select_or_olt_ueq_ogt:
590 ; CHECK-LABEL: ; %bb.0:
591 ; CHECK-NEXT: fcmp d0, d1
592 ; CHECK-NEXT: fccmp d2, d3, #4, pl
593 ; CHECK-NEXT: fccmp d2, d3, #1, ne
594 ; CHECK-NEXT: fccmp d4, d5, #0, vc
595 ; CHECK-NEXT: csel w0, w0, w1, gt
596 ; CHECK-NEXT: ret
597 define i32 @select_or_olt_ueq_ogt(double %v0, double %v1, double %v2, double %v3, double %v4, double %v5, i32 %a, i32 %b) #0 {
598   %c0 = fcmp olt double %v0, %v1
599   %c1 = fcmp ueq double %v2, %v3
600   %c2 = fcmp ogt double %v4, %v5
601   %c3 = or i1 %c1, %c0
602   %cr = or i1 %c2, %c3
603   %sel = select i1 %cr, i32 %a, i32 %b
604   ret i32 %sel
607 ; Verify that we correctly promote f16.
609 ; CHECK-LABEL: half_select_and_olt_oge:
610 ; CHECK-LABEL: ; %bb.0:
611 ; CHECK-DAG:  fcvt [[S0:s[0-9]+]], h0
612 ; CHECK-DAG:  fcvt [[S1:s[0-9]+]], h1
613 ; CHECK-NEXT: fcmp [[S0]], [[S1]]
614 ; CHECK-DAG:  fcvt [[S2:s[0-9]+]], h2
615 ; CHECK-DAG:  fcvt [[S3:s[0-9]+]], h3
616 ; CHECK-NEXT: fccmp [[S2]], [[S3]], #8, mi
617 ; CHECK-NEXT: csel w0, w0, w1, ge
618 ; CHECK-NEXT: ret
619 define i32 @half_select_and_olt_oge(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 {
620   %c0 = fcmp olt half %v0, %v1
621   %c1 = fcmp oge half %v2, %v3
622   %cr = and i1 %c1, %c0
623   %sel = select i1 %cr, i32 %a, i32 %b
624   ret i32 %sel
627 ; CHECK-LABEL: half_select_and_olt_one:
628 ; CHECK-LABEL: ; %bb.0:
629 ; CHECK-DAG:  fcvt [[S0:s[0-9]+]], h0
630 ; CHECK-DAG:  fcvt [[S1:s[0-9]+]], h1
631 ; CHECK-NEXT: fcmp [[S0]], [[S1]]
632 ; CHECK-DAG:  fcvt [[S2:s[0-9]+]], h2
633 ; CHECK-DAG:  fcvt [[S3:s[0-9]+]], h3
634 ; CHECK-NEXT: fccmp [[S2]], [[S3]], #4, mi
635 ; CHECK-NEXT: fccmp [[S2]], [[S3]], #1, ne
636 ; CHECK-NEXT: csel w0, w0, w1, vc
637 ; CHECK-NEXT: ret
638 define i32 @half_select_and_olt_one(half %v0, half %v1, half %v2, half %v3, i32 %a, i32 %b) #0 {
639   %c0 = fcmp olt half %v0, %v1
640   %c1 = fcmp one half %v2, %v3
641   %cr = and i1 %c1, %c0
642   %sel = select i1 %cr, i32 %a, i32 %b
643   ret i32 %sel
646 ; Also verify that we don't try to generate f128 FCCMPs, using RT calls instead.
648 ; CHECK-LABEL: f128_select_and_olt_oge:
649 ; CHECK: bl ___lttf2
650 ; CHECK: bl ___getf2
651 define i32 @f128_select_and_olt_oge(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32 %b) #0 {
652   %c0 = fcmp olt fp128 %v0, %v1
653   %c1 = fcmp oge fp128 %v2, %v3
654   %cr = and i1 %c1, %c0
655   %sel = select i1 %cr, i32 %a, i32 %b
656   ret i32 %sel
659 ; This testcase resembles the core problem of http://llvm.org/PR39550
660 ; (an OR operation is 2 levels deep but needs to be implemented first)
661 ; CHECK-LABEL: deep_or
662 ; CHECK: cmp w2, #20
663 ; CHECK-NEXT: ccmp w2, #15, #4, ne
664 ; CHECK-NEXT: ccmp w1, #0, #4, eq
665 ; CHECK-NEXT: ccmp w0, #0, #4, ne
666 ; CHECK-NEXT: csel w0, w4, w5, ne
667 ; CHECK-NEXT: ret
668 define i32 @deep_or(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
669   %c0 = icmp ne i32 %a0, 0
670   %c1 = icmp ne i32 %a1, 0
671   %c2 = icmp eq i32 %a2, 15
672   %c3 = icmp eq i32 %a2, 20
674   %or = or i1 %c2, %c3
675   %and0 = and i1 %or, %c1
676   %and1 = and i1 %and0, %c0
677   %sel = select i1 %and1, i32 %x, i32 %y
678   ret i32 %sel
681 ; Variation of deep_or, we still need to implement the OR first though.
682 ; CHECK-LABEL: deep_or1
683 ; CHECK: cmp w2, #20
684 ; CHECK-NEXT: ccmp w2, #15, #4, ne
685 ; CHECK-NEXT: ccmp w0, #0, #4, eq
686 ; CHECK-NEXT: ccmp w1, #0, #4, ne
687 ; CHECK-NEXT: csel w0, w4, w5, ne
688 ; CHECK-NEXT: ret
689 define i32 @deep_or1(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
690   %c0 = icmp ne i32 %a0, 0
691   %c1 = icmp ne i32 %a1, 0
692   %c2 = icmp eq i32 %a2, 15
693   %c3 = icmp eq i32 %a2, 20
695   %or = or i1 %c2, %c3
696   %and0 = and i1 %c0, %or
697   %and1 = and i1 %and0, %c1
698   %sel = select i1 %and1, i32 %x, i32 %y
699   ret i32 %sel
702 ; Variation of deep_or, we still need to implement the OR first though.
703 ; CHECK-LABEL: deep_or2
704 ; CHECK: cmp w2, #20
705 ; CHECK-NEXT: ccmp w2, #15, #4, ne
706 ; CHECK-NEXT: ccmp w1, #0, #4, eq
707 ; CHECK-NEXT: ccmp w0, #0, #4, ne
708 ; CHECK-NEXT: csel w0, w4, w5, ne
709 ; CHECK-NEXT: ret
710 define i32 @deep_or2(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
711   %c0 = icmp ne i32 %a0, 0
712   %c1 = icmp ne i32 %a1, 0
713   %c2 = icmp eq i32 %a2, 15
714   %c3 = icmp eq i32 %a2, 20
716   %or = or i1 %c2, %c3
717   %and0 = and i1 %c0, %c1
718   %and1 = and i1 %and0, %or
719   %sel = select i1 %and1, i32 %x, i32 %y
720   ret i32 %sel
723 attributes #0 = { nounwind }