xref: /llvm-project/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll (revision c17040599666c1f14906a899cabcf545c2c85744)
1; Test passing variable argument lists in 64-bit calls on z/OS.
2; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z10 | FileCheck %s
3; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z14 | FileCheck %s -check-prefix=ARCH12
4; CHECK-LABEL: call_vararg_double0:
5; CHECK:         stmg 6,7,1872(4)
6; CHECK-NEXT:    aghi 4,-192
7; CHECK-NEXT:    lg 6,8(5)
8; CHECK-NEXT:    lg 5,0(5)
9; CHECK-NEXT:    llihf 3,1074118262
10; CHECK-NEXT:    oilf 3,3367254360
11; CHECK-NEXT:    lghi 1,1
12; CHECK-NEXT:    lghi 2,2
13; CHECK-NEXT:    basr 7,6
14; CHECK-NEXT:    bcr 0,0
15; CHECK-NEXT:    lg 7,2072(4)
16; CHECK-NEXT:    aghi 4,192
17; CHECK-NEXT:    b 2(7)
18define i64 @call_vararg_double0() {
19entry:
20  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 2.718000e+00)
21  ret i64 %retval
22}
23
24; CHECK-LABEL: call_vararg_double1:
25; CHECK:         stmg 6,7,1872(4)
26; CHECK-NEXT:    aghi 4,-192
27; CHECK-NEXT:    llihf 0,1074118262
28; CHECK-NEXT:    oilf 0,3367254360
29; CHECK-NEXT:    lg 6,8(5)
30; CHECK-NEXT:    lg 5,0(5)
31; CHECK-NEXT:    llihf 3,1074340036
32; CHECK-NEXT:    oilf 3,2611340116
33; CHECK-NEXT:    lghi 1,1
34; CHECK-NEXT:    lghi 2,2
35; CHECK-NEXT:    stg 0,2200(4)
36; CHECK-NEXT:    basr 7,6
37; CHECK-NEXT:    bcr 0,0
38; CHECK-NEXT:    lg 7,2072(4)
39; CHECK-NEXT:    aghi 4,192
40; CHECK-NEXT:    b 2(7)
41define i64 @call_vararg_double1() {
42entry:
43  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 3.141000e+00, double 2.718000e+00)
44  ret i64 %retval
45}
46
47; CHECK-LABEL: call_vararg_double2:
48; CHECK:         stmg 6,7,1872(4)
49; CHECK-NEXT:    aghi 4,-192
50; CHECK-NEXT:    lg 6,24(5)
51; CHECK-NEXT:    lg 5,16(5)
52; CHECK-NEXT:    llihf 2,1074118262
53; CHECK-NEXT:    oilf 2,3367254360
54; CHECK-NEXT:    lghi 1,8200
55; CHECK-NEXT:    basr 7,6
56; CHECK-NEXT:    bcr 0,0
57; CHECK-NEXT:    lg 7,2072(4)
58; CHECK-NEXT:    aghi 4,192
59; CHECK-NEXT:    b 2(7)
60define i64 @call_vararg_double2() {
61entry:
62  %retval = call i64 (i64, ...) @pass_vararg2(i64 8200, double 2.718000e+00)
63  ret i64 %retval
64}
65
66; CHECK-LABEL: call_vararg_double3:
67; CHECK:         stmg 6,7,1872(4)
68; CHECK-NEXT:    aghi 4,-192
69; CHECK-NEXT:    llihf 0,1072703839
70; CHECK-NEXT:    oilf 0,2861204133
71; CHECK-NEXT:    lg 6,40(5)
72; CHECK-NEXT:    lg 5,32(5)
73; CHECK-NEXT:    llihf 1,1074118262
74; CHECK-NEXT:    oilf 1,3367254360
75; CHECK-NEXT:    llihf 2,1074340036
76; CHECK-NEXT:    oilf 2,2611340116
77; CHECK-NEXT:    llihf 3,1073127358
78; CHECK-NEXT:    oilf 3,1992864825
79; CHECK-NEXT:    stg 0,2200(4)
80; CHECK-NEXT:    basr 7,6
81; CHECK-NEXT:    bcr 0,0
82; CHECK-NEXT:    lg 7,2072(4)
83; CHECK-NEXT:    aghi 4,192
84; CHECK-NEXT:    b 2(7)
85define i64 @call_vararg_double3() {
86entry:
87  %retval = call i64 (...) @pass_vararg3(double 2.718000e+00, double 3.141000e+00, double 1.414000e+00, double 1.010101e+00)
88  ret i64 %retval
89}
90
91;; TODO: The extra COPY after LGDR is unnecessary (machine-scheduler introduces the overlap).
92; CHECK-LABEL: call_vararg_both0:
93; CHECK:         stmg 6,7,1872(4)
94; CHECK-NEXT:    aghi 4,-192
95; CHECK-NEXT:    lg 6,40(5)
96; CHECK-NEXT:    lg 5,32(5)
97; CHECK-NEXT:    lgdr 0,0
98; CHECK-NEXT:    lgr 2,1
99; CHECK-NEXT:    lgr 1,0
100; CHECK-NEXT:    basr 7,6
101; CHECK-NEXT:    bcr 0,0
102; CHECK-NEXT:    lg 7,2072(4)
103; CHECK-NEXT:    aghi 4,192
104; CHECK-NEXT:    b 2(7)
105define i64 @call_vararg_both0(i64 %arg0, double %arg1) {
106  %retval  = call i64(...) @pass_vararg3(double %arg1, i64 %arg0)
107  ret i64 %retval
108}
109
110; CHECK-LABEL: call_vararg_long_double0:
111; CHECK:         stmg 6,7,1872(4)
112; CHECK-NEXT:    aghi 4,-192
113; CHECK-NEXT:    larl 1,L#CPI5_0
114; CHECK-NEXT:    ld 0,0(1)
115; CHECK-NEXT:    ld 2,8(1)
116; CHECK-NEXT:    lg 6,8(5)
117; CHECK-NEXT:    lg 5,0(5)
118; CHECK-NEXT:    lgdr 3,0
119; CHECK-NEXT:    lghi 1,1
120; CHECK-NEXT:    lghi 2,2
121; CHECK-NEXT:    std 0,2192(4)
122; CHECK-NEXT:    std 2,2200(4)
123; CHECK-NEXT:    basr 7,6
124; CHECK-NEXT:    bcr 0,0
125; CHECK-NEXT:    lg 7,2072(4)
126; CHECK-NEXT:    aghi 4,192
127; CHECK-NEXT:    b 2(7)
128define i64 @call_vararg_long_double0() {
129entry:
130  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 0xLE0FC1518450562CD4000921FB5444261)
131  ret i64 %retval
132}
133
134; CHECK-LABEL: call_vararg_long_double1:
135; CHECK:         stmg 6,7,1872(4)
136; CHECK-NEXT:    aghi 4,-192
137; CHECK-NEXT:    lg 6,8(5)
138; CHECK-NEXT:    lg 5,0(5)
139; CHECK-NEXT:    lgdr 3,0
140; CHECK-NEXT:    lghi 1,1
141; CHECK-NEXT:    lghi 2,2
142; CHECK-NEXT:    std 0,2192(4)
143; CHECK-NEXT:    std 2,2200(4)
144; CHECK-NEXT:    basr 7,6
145; CHECK-NEXT:    bcr 0,0
146; CHECK-NEXT:    lg 7,2072(4)
147; CHECK-NEXT:    aghi 4,192
148; CHECK-NEXT:    b 2(7)
149define i64 @call_vararg_long_double1(fp128 %arg0) {
150entry:
151  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0)
152  ret i64 %retval
153}
154
155; CHECK-LABEL: call_vararg_long_double2
156; CHECK-LABEL: call_vararg_long_double2:
157; CHECK:         stmg 6,7,1872(4)
158; CHECK-NEXT:    aghi 4,-192
159; CHECK-NEXT:    std 4,2208(4)
160; CHECK-NEXT:    std 6,2216(4)
161; CHECK-NEXT:    lg 6,8(5)
162; CHECK-NEXT:    lg 5,0(5)
163; CHECK-NEXT:    lgdr 3,0
164; CHECK-NEXT:    lghi 1,1
165; CHECK-NEXT:    lghi 2,2
166; CHECK-NEXT:    std 0,2192(4)
167; CHECK-NEXT:    std 2,2200(4)
168; CHECK-NEXT:    basr 7,6
169; CHECK-NEXT:    bcr 0,0
170; CHECK-NEXT:    lg 7,2072(4)
171; CHECK-NEXT:    aghi 4,192
172; CHECK-NEXT:    b 2(7)
173define i64 @call_vararg_long_double2(fp128 %arg0, fp128 %arg1) {
174entry:
175  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0, fp128 %arg1)
176  ret i64 %retval
177}
178
179; CHECK-LABEL: call_vararg_long_double3:
180; CHECK:         stmg 6,7,1872(4)
181; CHECK-NEXT:    aghi 4,-192
182; CHECK-NEXT:    lg 6,40(5)
183; CHECK-NEXT:    lg 5,32(5)
184; CHECK-NEXT:    lgdr 3,2
185; CHECK-NEXT:    lgdr 2,0
186; CHECK-NEXT:    basr 7,6
187; CHECK-NEXT:    bcr 0,0
188; CHECK-NEXT:    lg 7,2072(4)
189; CHECK-NEXT:    aghi 4,192
190; CHECK-NEXT:    b 2(7)
191define i64 @call_vararg_long_double3(fp128 %arg0) {
192entry:
193  %retval = call i64 (...) @pass_vararg3(fp128 %arg0)
194  ret i64 %retval
195}
196
197; ARCH12-LABEL: call_vec_vararg_test0
198; ARCH12: vlgvg 3,24,1
199; ARCH12: vlgvg 2,24,0
200; ARCH12: lghi  1,1
201define void @call_vec_vararg_test0(<2 x double> %v) {
202  %retval = call i64(i64, ...) @pass_vararg2(i64 1, <2 x double> %v)
203  ret void
204}
205
206; ARCH12-LABEL: call_vec_vararg_test1
207; ARCH12: larl  1,L#CPI10_0
208; ARCH12: vl    0,0(1),3
209; ARCH12: vlgvg 3,24,0
210; ARCH12: vrepg 2,0,1
211; ARCH12: vst   25,2208(4),3
212; ARCH12: vst   24,2192(4),3
213define void @call_vec_vararg_test1(<4 x i32> %v, <2 x i64> %w) {
214  %retval = call i64(fp128, ...) @pass_vararg1(fp128 0xLE0FC1518450562CD4000921FB5444261, <4 x i32> %v, <2 x i64> %w)
215  ret void
216}
217
218; ARCH12-LABEL: call_vec_char_vararg_straddle
219; ARCH12: vlgvg 3,24,0
220; ARCH12: lghi  1,1
221; ARCH12: lghi  2,2
222; ARCH12: vst   24,2192(4),3
223define void @call_vec_char_vararg_straddle(<16 x i8> %v) {
224  %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <16 x i8> %v)
225  ret void
226}
227
228; ARCH12-LABEL: call_vec_short_vararg_straddle
229; ARCH12: vlgvg 3,24,0
230; ARCH12: lghi  1,1
231; ARCH12: lghi  2,2
232; ARCH12: vst   24,2192(4),3
233define void @call_vec_short_vararg_straddle(<8 x i16> %v) {
234  %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <8 x i16> %v)
235  ret void
236}
237
238; ARCH12-LABEL: call_vec_int_vararg_straddle
239; ARCH12: vlgvg 3,24,0
240; ARCH12: lghi  1,1
241; ARCH12: lghi  2,2
242; ARCH12: vst 24,2192(4),3
243define void @call_vec_int_vararg_straddle(<4 x i32> %v) {
244  %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <4 x i32> %v)
245  ret void
246}
247
248; ARCH12-LABEL: call_vec_double_vararg_straddle
249; ARCH12: vlgvg 3,24,0
250; ARCH12: lghi  1,1
251; ARCH12: lghi  2,2
252; ARCH12: vst 24,2192(4),3
253define void @call_vec_double_vararg_straddle(<2 x double> %v) {
254  %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <2 x double> %v)
255  ret void
256}
257
258; CHECK-LABEL: call_vararg_integral0:
259; CHECK:         stmg 6,7,1872(4)
260; CHECK-NEXT:    aghi 4,-192
261; CHECK-NEXT:    lg 0,2392(4)
262; CHECK-NEXT:    lg 6,40(5)
263; CHECK-NEXT:    lg 5,32(5)
264; CHECK-NEXT:    stg 0,2200(4)
265; CHECK-NEXT:    basr 7,6
266; CHECK-NEXT:    bcr 0,0
267; CHECK-NEXT:    lg 7,2072(4)
268; CHECK-NEXT:    aghi 4,192
269; CHECK-NEXT:    b 2(7)
270define i64 @call_vararg_integral0(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) {
271entry:
272  %retval = call i64(...) @pass_vararg3(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3)
273  ret i64 %retval
274}
275
276; CHECK-LABEL: call_vararg_float0:
277; CHECK:         stmg 6,7,1872(4)
278; CHECK-NEXT:    aghi 4,-192
279; CHECK-NEXT:    lg 6,24(5)
280; CHECK-NEXT:    lg 5,16(5)
281; CHECK-NEXT:    lghi 1,1
282; CHECK-NEXT:    llihf 2,1073692672
283; CHECK-NEXT:    basr 7,6
284; CHECK-NEXT:    bcr 0,0
285; CHECK-NEXT:    lg 7,2072(4)
286; CHECK-NEXT:    aghi 4,192
287; CHECK-NEXT:    b 2(7)
288define i64 @call_vararg_float0() {
289entry:
290  %retval = call i64 (i64, ...) @pass_vararg2(i64 1, float 1.953125)
291  ret i64 %retval
292}
293
294; CHECK-LABEL: call_vararg_float1:
295; CHECK:         stmg 6,7,1872(4)
296; CHECK-NEXT:    aghi 4,-192
297; CHECK-NEXT:    lg 6,72(5)
298; CHECK-NEXT:    lg 5,64(5)
299; CHECK-NEXT:    larl 1,L#CPI17_0
300; CHECK-NEXT:    le 0,0(1)
301; CHECK-NEXT:    llihf 0,1073692672
302; CHECK-NEXT:    llihh 2,16384
303; CHECK-NEXT:    llihh 3,16392
304; CHECK-NEXT:    stg 0,2200(4)
305; CHECK-NEXT:    basr 7,6
306; CHECK-NEXT:    bcr 0,0
307; CHECK-NEXT:    lg 7,2072(4)
308; CHECK-NEXT:    aghi 4,192
309; CHECK-NEXT:    b 2(7)
310define i64 @call_vararg_float1() {
311entry:
312  %retval = call i64 (float, ...) @pass_vararg4(float 1.0, float 2.0, float 3.0, float 1.953125)
313  ret i64 %retval
314}
315
316; Derived from C source:
317; #define _VARARG_EXT_
318; #include <stdarg.h>
319;
320; long pass(long x, ...) {
321;   va_list va;
322;   va_start(va, x);
323;   long ret = va_arg(va, long);
324;   va_end(va);
325;   return ret;
326; }
327;
328; CHECK-LABEL: pass_vararg:
329; CHECK:         stmg 6,7,1904(4)
330; CHECK-NEXT:    aghi 4,-160
331; CHECK-NEXT:    stg 2,2344(4)
332; CHECK-NEXT:    stg 3,2352(4)
333; CHECK-NEXT:    la 0,2352(4)
334; CHECK-NEXT:    stg 0,2200(4)
335; CHECK-NEXT:    lg 3,2344(4)
336; CHECK-NEXT:    lg 7,2072(4)
337; CHECK-NEXT:    aghi 4,160
338; CHECK-NEXT:    b 2(7)
339define hidden i64 @pass_vararg(i64 %x, ...) {
340entry:
341  %va = alloca ptr, align 8
342  call void @llvm.va_start(ptr %va)
343  %argp.cur = load ptr, ptr %va, align 8
344  %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 8
345  store ptr %argp.next, ptr %va, align 8
346  %ret = load i64, ptr %argp.cur, align 8
347  call void @llvm.va_end(ptr %va)
348  ret i64 %ret
349}
350
351declare void @llvm.va_start(ptr)
352declare void @llvm.va_end(ptr)
353
354declare i64 @pass_vararg0(i64 %arg0, i64 %arg1, ...)
355declare i64 @pass_vararg1(fp128 %arg0, ...)
356declare i64 @pass_vararg2(i64 %arg0, ...)
357declare i64 @pass_vararg3(...)
358declare i64 @pass_vararg4(float, ...)
359