1; RUN: llc < %s -mcpu=cyclone -verify-machineinstrs -aarch64-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: speculate_division
108; CHECK-NOT: cmp
109; CHECK: sdiv
110; CHECK: cmp
111; CHECK-NEXT: ccmp
112define i32 @speculate_division(i32 %a, i32 %b) nounwind ssp {
113entry:
114  %cmp = icmp sgt i32 %a, 0
115  br i1 %cmp, label %land.lhs.true, label %if.end
116
117land.lhs.true:
118  %div = sdiv i32 %b, %a
119  %cmp1 = icmp slt i32 %div, 17
120  br i1 %cmp1, label %if.then, label %if.end
121
122if.then:
123  %call = tail call i32 @foo() nounwind
124  br label %if.end
125
126if.end:
127  ret i32 7
128}
129
130; Floating point compare.
131; CHECK: single_fcmp
132; CHECK: cmp
133; CHECK-NOT: b.
134; CHECK: fccmp {{.*}}, #8, ge
135; CHECK: b.lt
136define i32 @single_fcmp(i32 %a, float %b) nounwind ssp {
137entry:
138  %cmp = icmp sgt i32 %a, 0
139  br i1 %cmp, label %land.lhs.true, label %if.end
140
141land.lhs.true:
142  %conv = sitofp i32 %a to float
143  %div = fdiv float %b, %conv
144  %cmp1 = fcmp oge float %div, 1.700000e+01
145  br i1 %cmp1, label %if.then, label %if.end
146
147if.then:
148  %call = tail call i32 @foo() nounwind
149  br label %if.end
150
151if.end:
152  ret i32 7
153}
154
155; Chain multiple compares.
156; CHECK: multi_different
157; CHECK: cmp
158; CHECK: ccmp
159; CHECK: ccmp
160; CHECK: b.
161define void @multi_different(i32 %a, i32 %b, i32 %c) nounwind ssp {
162entry:
163  %cmp = icmp sgt i32 %a, %b
164  br i1 %cmp, label %land.lhs.true, label %if.end
165
166land.lhs.true:
167  %div = sdiv i32 %b, %a
168  %cmp1 = icmp eq i32 %div, 5
169  %cmp4 = icmp sgt i32 %div, %c
170  %or.cond = and i1 %cmp1, %cmp4
171  br i1 %or.cond, label %if.then, label %if.end
172
173if.then:
174  %call = tail call i32 @foo() nounwind
175  br label %if.end
176
177if.end:
178  ret void
179}
180
181; Convert a cbz in the head block.
182; CHECK: cbz_head
183; CHECK: cmp w0, #0
184; CHECK: ccmp
185define i32 @cbz_head(i32 %a, i32 %b) nounwind ssp {
186entry:
187  %cmp = icmp eq i32 %a, 0
188  %cmp1 = icmp ne i32 %b, 17
189  %or.cond = or i1 %cmp, %cmp1
190  br i1 %or.cond, label %if.then, label %if.end
191
192if.then:
193  %call = tail call i32 @foo() nounwind
194  br label %if.end
195
196if.end:
197  ret i32 7
198}
199
200; Check that the immediate operand is in range. The ccmp instruction encodes a
201; smaller range of immediates than subs/adds.
202; The ccmp immediates must be in the range 0-31.
203; CHECK: immediate_range
204; CHECK-NOT: ccmp
205define i32 @immediate_range(i32 %a, i32 %b) nounwind ssp {
206entry:
207  %cmp = icmp eq i32 %a, 5
208  %cmp1 = icmp eq i32 %b, 32
209  %or.cond = or i1 %cmp, %cmp1
210  br i1 %or.cond, label %if.then, label %if.end
211
212if.then:
213  %call = tail call i32 @foo() nounwind
214  br label %if.end
215
216if.end:
217  ret i32 7
218}
219
220; Convert a cbz in the second block.
221; CHECK: cbz_second
222; CHECK: cmp w0, #0
223; CHECK: ccmp w1, #0, #0, ne
224; CHECK: b.eq
225define i32 @cbz_second(i32 %a, i32 %b) nounwind ssp {
226entry:
227  %cmp = icmp eq i32 %a, 0
228  %cmp1 = icmp ne i32 %b, 0
229  %or.cond = or i1 %cmp, %cmp1
230  br i1 %or.cond, label %if.then, label %if.end
231
232if.then:
233  %call = tail call i32 @foo() nounwind
234  br label %if.end
235
236if.end:
237  ret i32 7
238}
239
240; Convert a cbnz in the second block.
241; CHECK: cbnz_second
242; CHECK: cmp w0, #0
243; CHECK: ccmp w1, #0, #4, ne
244; CHECK: b.ne
245define i32 @cbnz_second(i32 %a, i32 %b) nounwind ssp {
246entry:
247  %cmp = icmp eq i32 %a, 0
248  %cmp1 = icmp eq i32 %b, 0
249  %or.cond = or i1 %cmp, %cmp1
250  br i1 %or.cond, label %if.then, label %if.end
251
252if.then:
253  %call = tail call i32 @foo() nounwind
254  br label %if.end
255
256if.end:
257  ret i32 7
258}
259declare i32 @foo()
260
261%str1 = type { %str2 }
262%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* }
263
264; Test case distilled from 126.gcc.
265; The phi in sw.bb.i.i gets multiple operands for the %entry predecessor.
266; CHECK: build_modify_expr
267define void @build_modify_expr() nounwind ssp {
268entry:
269  switch i32 undef, label %sw.bb.i.i [
270    i32 69, label %if.end85
271    i32 70, label %if.end85
272    i32 71, label %if.end85
273    i32 72, label %if.end85
274    i32 73, label %if.end85
275    i32 105, label %if.end85
276    i32 106, label %if.end85
277  ]
278
279if.end85:
280  ret void
281
282sw.bb.i.i:
283  %ref.tr.i.i = phi %str1* [ %0, %sw.bb.i.i ], [ undef, %entry ]
284  %operands.i.i = getelementptr inbounds %str1, %str1* %ref.tr.i.i, i64 0, i32 0, i32 2
285  %arrayidx.i.i = bitcast i32* %operands.i.i to %str1**
286  %0 = load %str1*, %str1** %arrayidx.i.i, align 8
287  %code1.i.i.phi.trans.insert = getelementptr inbounds %str1, %str1* %0, i64 0, i32 0, i32 0, i64 16
288  br label %sw.bb.i.i
289}
290