1; RUN: llc < %s -debugify-and-strip-all-safe -mcpu=cyclone -verify-machineinstrs -aarch64-enable-ccmp -aarch64-stress-ccmp | FileCheck %s
2target triple = "arm64-apple-ios"
3
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
11define i32 @single_same(i32 %a, i32 %b) nounwind ssp {
12entry:
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
17
18if.then:
19  %call = tail call i32 @foo() nounwind
20  br label %if.end
21
22if.end:
23  ret i32 7
24}
25
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
34define i32 @single_different(i32 %a, i32 %b) nounwind ssp {
35entry:
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
40
41if.then:
42  %call = tail call i32 @foo() nounwind
43  br label %if.end
44
45if.end:
46  ret i32 7
47}
48
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
55define i32 @single_flagclobber(i32 %a, i32 %b) nounwind ssp {
56entry:
57  %cmp = icmp eq i32 %a, 5
58  br i1 %cmp, label %if.then, label %lor.lhs.false
59
60lor.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
67
68if.then:                                          ; preds = %lor.lhs.false, %entry
69  %call = tail call i32 @foo() nounwind
70  br label %if.end
71
72if.end:                                           ; preds = %if.then, %lor.lhs.false
73  ret i32 7
74}
75
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
82define i32 @single_flagclobber_tbz(i32 %a, i32 %b) nounwind ssp {
83entry:
84  %cmp = icmp eq i32 %a, 5
85  br i1 %cmp, label %if.then, label %lor.lhs.false
86
87lor.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
95
96if.then:                                          ; preds = %lor.lhs.false, %entry
97  %call = tail call i32 @foo() nounwind
98  br label %if.end
99
100if.end:                                           ; preds = %if.then, %lor.lhs.false
101  ret i32 7
102}
103
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
115define i32 @speculate_division(i32 %a, i32 %b) nounwind ssp {
116entry:
117  %cmp = icmp sgt i32 %a, 0
118  br i1 %cmp, label %land.lhs.true, label %if.end
119
120land.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
124
125if.then:
126  %call = tail call i32 @foo() nounwind
127  br label %if.end
128
129if.end:
130  ret i32 7
131}
132
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
140define i32 @single_fcmp(i32 %a, float %b) nounwind ssp {
141entry:
142  %cmp = icmp sgt i32 %a, 0
143  br i1 %cmp, label %land.lhs.true, label %if.end
144
145land.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
150
151if.then:
152  %call = tail call i32 @foo() nounwind
153  br label %if.end
154
155if.end:
156  ret i32 7
157}
158
159; Chain multiple compares.
160; CHECK: multi_different
161; CHECK: cmp
162; CHECK: ccmp
163; CHECK: ccmp
164; CHECK: b.
165define void @multi_different(i32 %a, i32 %b, i32 %c) nounwind ssp {
166entry:
167  %cmp = icmp sgt i32 %a, %b
168  br i1 %cmp, label %land.lhs.true, label %if.end
169
170land.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
176
177if.then:
178  %call = tail call i32 @foo() nounwind
179  br label %if.end
180
181if.end:
182  ret void
183}
184
185; Convert a cbz in the head block.
186; CHECK: cbz_head
187; CHECK: cmp w0, #0
188; CHECK: ccmp
189define i32 @cbz_head(i32 %a, i32 %b) nounwind ssp {
190entry:
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
195
196if.then:
197  %call = tail call i32 @foo() nounwind
198  br label %if.end
199
200if.end:
201  ret i32 7
202}
203
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
209define i32 @immediate_range(i32 %a, i32 %b) nounwind ssp {
210entry:
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
215
216if.then:
217  %call = tail call i32 @foo() nounwind
218  br label %if.end
219
220if.end:
221  ret i32 7
222}
223
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
229define i32 @cbz_second(i32 %a, i32 %b) nounwind ssp {
230entry:
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
235
236if.then:
237  %call = tail call i32 @foo() nounwind
238  br label %if.end
239
240if.end:
241  ret i32 7
242}
243
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
249define i32 @cbnz_second(i32 %a, i32 %b) nounwind ssp {
250entry:
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
255
256if.then:
257  %call = tail call i32 @foo() nounwind
258  br label %if.end
259
260if.end:
261  ret i32 7
262}
263declare i32 @foo()
264
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* }
267
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
271define void @build_modify_expr() nounwind ssp {
272entry:
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  ]
282
283if.end85:
284  ret void
285
286sw.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
293}
294
295; CHECK-LABEL: select_and
296define 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
306}
307
308; CHECK-LABEL: select_or
309define 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
319}
320
321; CHECK-LABEL: gccbug
322define 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
332
333  %or = or i1 %cmp2, %cmp1
334  %and = and i1 %or, %cmp0
335
336  %sel = select i1 %and, i64 2, i64 1
337  ret i64 %sel
338}
339
340; CHECK-LABEL: select_ororand
341define 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
357}
358
359; CHECK-LABEL: select_andor
360define 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
373}
374
375; CHECK-LABEL: select_noccmp1
376define 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
401}
402
403@g = global i32 0
404
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
408define 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
428}
429
430; The following is not possible to implement with a single cmp;ccmp;csel
431; sequence.
432; CHECK-LABEL: select_noccmp3
433define 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
447}
448
449; Test the IR CCs that expand to two cond codes.
450
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
458define 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
464}
465
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
473define 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
479}
480
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
488define 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
494}
495
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
503define 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
509}
510
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
518define 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
524}
525
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
533define 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
539}
540
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
548define 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
554}
555
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
563define 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
569}
570
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
579define 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
587}
588
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
597define 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
605}
606
607; Verify that we correctly promote f16.
608
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
619define 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
625}
626
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
638define 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
644}
645
646; Also verify that we don't try to generate f128 FCCMPs, using RT calls instead.
647
648; CHECK-LABEL: f128_select_and_olt_oge:
649; CHECK: bl ___lttf2
650; CHECK: bl ___getf2
651define 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
657}
658
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
668define 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
673
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
679}
680
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
689define 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
694
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
700}
701
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
710define 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
715
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
721}
722
723attributes #0 = { nounwind }
724