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