1; Test 64-bit comparison in which the second operand is a zero-extended i32.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5declare i64 @foo()
6
7; Check unsigned register comparison.
8define double @f1(double %a, double %b, i64 %i1, i32 %unext) {
9; CHECK-LABEL: f1:
10; CHECK: clgfr %r2, %r3
11; CHECK-NEXT: jl
12; CHECK: ldr %f0, %f2
13; CHECK: br %r14
14  %i2 = zext i32 %unext to i64
15  %cond = icmp ult i64 %i1, %i2
16  %res = select i1 %cond, double %a, double %b
17  ret double %res
18}
19
20; ...and again with a different representation.
21define double @f2(double %a, double %b, i64 %i1, i64 %unext) {
22; CHECK-LABEL: f2:
23; CHECK: clgfr %r2, %r3
24; CHECK-NEXT: jl
25; CHECK: ldr %f0, %f2
26; CHECK: br %r14
27  %i2 = and i64 %unext, 4294967295
28  %cond = icmp ult i64 %i1, %i2
29  %res = select i1 %cond, double %a, double %b
30  ret double %res
31}
32
33; Check signed register comparison, which can't use CLGFR.
34define double @f3(double %a, double %b, i64 %i1, i32 %unext) {
35; CHECK-LABEL: f3:
36; CHECK-NOT: clgfr
37; CHECK: br %r14
38  %i2 = zext i32 %unext to i64
39  %cond = icmp slt i64 %i1, %i2
40  %res = select i1 %cond, double %a, double %b
41  ret double %res
42}
43
44; ...and again with a different representation
45define double @f4(double %a, double %b, i64 %i1, i64 %unext) {
46; CHECK-LABEL: f4:
47; CHECK-NOT: clgfr
48; CHECK: br %r14
49  %i2 = and i64 %unext, 4294967295
50  %cond = icmp slt i64 %i1, %i2
51  %res = select i1 %cond, double %a, double %b
52  ret double %res
53}
54
55; Check register equality.
56define double @f5(double %a, double %b, i64 %i1, i32 %unext) {
57; CHECK-LABEL: f5:
58; CHECK: clgfr %r2, %r3
59; CHECK-NEXT: je
60; CHECK: ldr %f0, %f2
61; CHECK: br %r14
62  %i2 = zext i32 %unext to i64
63  %cond = icmp eq i64 %i1, %i2
64  %res = select i1 %cond, double %a, double %b
65  ret double %res
66}
67
68; ...and again with a different representation
69define double @f6(double %a, double %b, i64 %i1, i64 %unext) {
70; CHECK-LABEL: f6:
71; CHECK: clgfr %r2, %r3
72; CHECK-NEXT: je
73; CHECK: ldr %f0, %f2
74; CHECK: br %r14
75  %i2 = and i64 %unext, 4294967295
76  %cond = icmp eq i64 %i1, %i2
77  %res = select i1 %cond, double %a, double %b
78  ret double %res
79}
80
81; Check register inequality.
82define double @f7(double %a, double %b, i64 %i1, i32 %unext) {
83; CHECK-LABEL: f7:
84; CHECK: clgfr %r2, %r3
85; CHECK-NEXT: jlh
86; CHECK: ldr %f0, %f2
87; CHECK: br %r14
88  %i2 = zext i32 %unext to i64
89  %cond = icmp ne i64 %i1, %i2
90  %res = select i1 %cond, double %a, double %b
91  ret double %res
92}
93
94; ...and again with a different representation
95define double @f8(double %a, double %b, i64 %i1, i64 %unext) {
96; CHECK-LABEL: f8:
97; CHECK: clgfr %r2, %r3
98; CHECK-NEXT: jlh
99; CHECK: ldr %f0, %f2
100; CHECK: br %r14
101  %i2 = and i64 %unext, 4294967295
102  %cond = icmp ne i64 %i1, %i2
103  %res = select i1 %cond, double %a, double %b
104  ret double %res
105}
106
107; Check unsigned comparison with memory.
108define double @f9(double %a, double %b, i64 %i1, i32 *%ptr) {
109; CHECK-LABEL: f9:
110; CHECK: clgf %r2, 0(%r3)
111; CHECK-NEXT: jl
112; CHECK: ldr %f0, %f2
113; CHECK: br %r14
114  %unext = load i32 *%ptr
115  %i2 = zext i32 %unext to i64
116  %cond = icmp ult i64 %i1, %i2
117  %res = select i1 %cond, double %a, double %b
118  ret double %res
119}
120
121; Check signed comparison with memory.
122define double @f10(double %a, double %b, i64 %i1, i32 *%ptr) {
123; CHECK-LABEL: f10:
124; CHECK-NOT: clgf
125; CHECK: br %r14
126  %unext = load i32 *%ptr
127  %i2 = zext i32 %unext to i64
128  %cond = icmp slt i64 %i1, %i2
129  %res = select i1 %cond, double %a, double %b
130  ret double %res
131}
132
133; Check memory equality.
134define double @f11(double %a, double %b, i64 %i1, i32 *%ptr) {
135; CHECK-LABEL: f11:
136; CHECK: clgf %r2, 0(%r3)
137; CHECK-NEXT: je
138; CHECK: ldr %f0, %f2
139; CHECK: br %r14
140  %unext = load i32 *%ptr
141  %i2 = zext i32 %unext to i64
142  %cond = icmp eq i64 %i1, %i2
143  %res = select i1 %cond, double %a, double %b
144  ret double %res
145}
146
147; Check memory inequality.
148define double @f12(double %a, double %b, i64 %i1, i32 *%ptr) {
149; CHECK-LABEL: f12:
150; CHECK: clgf %r2, 0(%r3)
151; CHECK-NEXT: jlh
152; CHECK: ldr %f0, %f2
153; CHECK: br %r14
154  %unext = load i32 *%ptr
155  %i2 = zext i32 %unext to i64
156  %cond = icmp ne i64 %i1, %i2
157  %res = select i1 %cond, double %a, double %b
158  ret double %res
159}
160
161; Check the high end of the aligned CLGF range.
162define double @f13(double %a, double %b, i64 %i1, i32 *%base) {
163; CHECK-LABEL: f13:
164; CHECK: clgf %r2, 524284(%r3)
165; CHECK-NEXT: jl
166; CHECK: ldr %f0, %f2
167; CHECK: br %r14
168  %ptr = getelementptr i32 *%base, i64 131071
169  %unext = load i32 *%ptr
170  %i2 = zext i32 %unext to i64
171  %cond = icmp ult i64 %i1, %i2
172  %res = select i1 %cond, double %a, double %b
173  ret double %res
174}
175
176; Check the next word up, which needs separate address logic.
177; Other sequences besides this one would be OK.
178define double @f14(double %a, double %b, i64 %i1, i32 *%base) {
179; CHECK-LABEL: f14:
180; CHECK: agfi %r3, 524288
181; CHECK: clgf %r2, 0(%r3)
182; CHECK-NEXT: jl
183; CHECK: ldr %f0, %f2
184; CHECK: br %r14
185  %ptr = getelementptr i32 *%base, i64 131072
186  %unext = load i32 *%ptr
187  %i2 = zext i32 %unext to i64
188  %cond = icmp ult i64 %i1, %i2
189  %res = select i1 %cond, double %a, double %b
190  ret double %res
191}
192
193; Check the high end of the negative aligned CLGF range.
194define double @f15(double %a, double %b, i64 %i1, i32 *%base) {
195; CHECK-LABEL: f15:
196; CHECK: clgf %r2, -4(%r3)
197; CHECK-NEXT: jl
198; CHECK: ldr %f0, %f2
199; CHECK: br %r14
200  %ptr = getelementptr i32 *%base, i64 -1
201  %unext = load i32 *%ptr
202  %i2 = zext i32 %unext to i64
203  %cond = icmp ult i64 %i1, %i2
204  %res = select i1 %cond, double %a, double %b
205  ret double %res
206}
207
208; Check the low end of the CLGF range.
209define double @f16(double %a, double %b, i64 %i1, i32 *%base) {
210; CHECK-LABEL: f16:
211; CHECK: clgf %r2, -524288(%r3)
212; CHECK-NEXT: jl
213; CHECK: ldr %f0, %f2
214; CHECK: br %r14
215  %ptr = getelementptr i32 *%base, i64 -131072
216  %unext = load i32 *%ptr
217  %i2 = zext i32 %unext to i64
218  %cond = icmp ult i64 %i1, %i2
219  %res = select i1 %cond, double %a, double %b
220  ret double %res
221}
222
223; Check the next word down, which needs separate address logic.
224; Other sequences besides this one would be OK.
225define double @f17(double %a, double %b, i64 %i1, i32 *%base) {
226; CHECK-LABEL: f17:
227; CHECK: agfi %r3, -524292
228; CHECK: clgf %r2, 0(%r3)
229; CHECK-NEXT: jl
230; CHECK: ldr %f0, %f2
231; CHECK: br %r14
232  %ptr = getelementptr i32 *%base, i64 -131073
233  %unext = load i32 *%ptr
234  %i2 = zext i32 %unext to i64
235  %cond = icmp ult i64 %i1, %i2
236  %res = select i1 %cond, double %a, double %b
237  ret double %res
238}
239
240; Check that CLGF allows an index.
241define double @f18(double %a, double %b, i64 %i1, i64 %base, i64 %index) {
242; CHECK-LABEL: f18:
243; CHECK: clgf %r2, 524284({{%r4,%r3|%r3,%r4}})
244; CHECK-NEXT: jl
245; CHECK: ldr %f0, %f2
246; CHECK: br %r14
247  %add1 = add i64 %base, %index
248  %add2 = add i64 %add1, 524284
249  %ptr = inttoptr i64 %add2 to i32 *
250  %unext = load i32 *%ptr
251  %i2 = zext i32 %unext to i64
252  %cond = icmp ult i64 %i1, %i2
253  %res = select i1 %cond, double %a, double %b
254  ret double %res
255}
256
257; Check that comparisons of spilled values can use CLGF rather than CLGFR.
258define i64 @f19(i32 *%ptr0) {
259; CHECK-LABEL: f19:
260; CHECK: brasl %r14, foo@PLT
261; CHECK: clgf {{%r[0-9]+}}, 16{{[04]}}(%r15)
262; CHECK: br %r14
263  %ptr1 = getelementptr i32 *%ptr0, i64 2
264  %ptr2 = getelementptr i32 *%ptr0, i64 4
265  %ptr3 = getelementptr i32 *%ptr0, i64 6
266  %ptr4 = getelementptr i32 *%ptr0, i64 8
267  %ptr5 = getelementptr i32 *%ptr0, i64 10
268  %ptr6 = getelementptr i32 *%ptr0, i64 12
269  %ptr7 = getelementptr i32 *%ptr0, i64 14
270  %ptr8 = getelementptr i32 *%ptr0, i64 16
271  %ptr9 = getelementptr i32 *%ptr0, i64 18
272
273  %val0 = load i32 *%ptr0
274  %val1 = load i32 *%ptr1
275  %val2 = load i32 *%ptr2
276  %val3 = load i32 *%ptr3
277  %val4 = load i32 *%ptr4
278  %val5 = load i32 *%ptr5
279  %val6 = load i32 *%ptr6
280  %val7 = load i32 *%ptr7
281  %val8 = load i32 *%ptr8
282  %val9 = load i32 *%ptr9
283
284  %frob0 = add i32 %val0, 100
285  %frob1 = add i32 %val1, 100
286  %frob2 = add i32 %val2, 100
287  %frob3 = add i32 %val3, 100
288  %frob4 = add i32 %val4, 100
289  %frob5 = add i32 %val5, 100
290  %frob6 = add i32 %val6, 100
291  %frob7 = add i32 %val7, 100
292  %frob8 = add i32 %val8, 100
293  %frob9 = add i32 %val9, 100
294
295  store i32 %frob0, i32 *%ptr0
296  store i32 %frob1, i32 *%ptr1
297  store i32 %frob2, i32 *%ptr2
298  store i32 %frob3, i32 *%ptr3
299  store i32 %frob4, i32 *%ptr4
300  store i32 %frob5, i32 *%ptr5
301  store i32 %frob6, i32 *%ptr6
302  store i32 %frob7, i32 *%ptr7
303  store i32 %frob8, i32 *%ptr8
304  store i32 %frob9, i32 *%ptr9
305
306  %ret = call i64 @foo()
307
308  %ext0 = zext i32 %frob0 to i64
309  %ext1 = zext i32 %frob1 to i64
310  %ext2 = zext i32 %frob2 to i64
311  %ext3 = zext i32 %frob3 to i64
312  %ext4 = zext i32 %frob4 to i64
313  %ext5 = zext i32 %frob5 to i64
314  %ext6 = zext i32 %frob6 to i64
315  %ext7 = zext i32 %frob7 to i64
316  %ext8 = zext i32 %frob8 to i64
317  %ext9 = zext i32 %frob9 to i64
318
319  %cmp0 = icmp ult i64 %ret, %ext0
320  %cmp1 = icmp ult i64 %ret, %ext1
321  %cmp2 = icmp ult i64 %ret, %ext2
322  %cmp3 = icmp ult i64 %ret, %ext3
323  %cmp4 = icmp ult i64 %ret, %ext4
324  %cmp5 = icmp ult i64 %ret, %ext5
325  %cmp6 = icmp ult i64 %ret, %ext6
326  %cmp7 = icmp ult i64 %ret, %ext7
327  %cmp8 = icmp ult i64 %ret, %ext8
328  %cmp9 = icmp ult i64 %ret, %ext9
329
330  %sel0 = select i1 %cmp0, i64 %ret, i64 0
331  %sel1 = select i1 %cmp1, i64 %sel0, i64 1
332  %sel2 = select i1 %cmp2, i64 %sel1, i64 2
333  %sel3 = select i1 %cmp3, i64 %sel2, i64 3
334  %sel4 = select i1 %cmp4, i64 %sel3, i64 4
335  %sel5 = select i1 %cmp5, i64 %sel4, i64 5
336  %sel6 = select i1 %cmp6, i64 %sel5, i64 6
337  %sel7 = select i1 %cmp7, i64 %sel6, i64 7
338  %sel8 = select i1 %cmp8, i64 %sel7, i64 8
339  %sel9 = select i1 %cmp9, i64 %sel8, i64 9
340
341  ret i64 %sel9
342}
343
344; Check the comparison can be reversed if that allows CLGFR to be used.
345define double @f20(double %a, double %b, i64 %i1, i32 %unext) {
346; CHECK-LABEL: f20:
347; CHECK: clgfr %r2, %r3
348; CHECK-NEXT: jh
349; CHECK: ldr %f0, %f2
350; CHECK: br %r14
351  %i2 = zext i32 %unext to i64
352  %cond = icmp ult i64 %i2, %i1
353  %res = select i1 %cond, double %a, double %b
354  ret double %res
355}
356
357; ...and again with the AND representation.
358define double @f21(double %a, double %b, i64 %i1, i64 %unext) {
359; CHECK-LABEL: f21:
360; CHECK: clgfr %r2, %r3
361; CHECK-NEXT: jh
362; CHECK: ldr %f0, %f2
363; CHECK: br %r14
364  %i2 = and i64 %unext, 4294967295
365  %cond = icmp ult i64 %i2, %i1
366  %res = select i1 %cond, double %a, double %b
367  ret double %res
368}
369
370; Check the comparison can be reversed if that allows CLGF to be used.
371define double @f22(double %a, double %b, i64 %i2, i32 *%ptr) {
372; CHECK-LABEL: f22:
373; CHECK: clgf %r2, 0(%r3)
374; CHECK-NEXT: jh {{\.L.*}}
375; CHECK: ldr %f0, %f2
376; CHECK: br %r14
377  %unext = load i32 *%ptr
378  %i1 = zext i32 %unext to i64
379  %cond = icmp ult i64 %i1, %i2
380  %res = select i1 %cond, double %a, double %b
381  ret double %res
382}
383