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: llihf 3, 1074118262
6 ; CHECK-NEXT: oilf 3, 3367254360
9 define i64 @call_vararg_double0() {
11 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 2.718000e+00)
15 ; CHECK-LABEL: call_vararg_double1
16 ; CHECK: llihf 0, 1074118262
17 ; CHECK-NEXT: oilf 0, 3367254360
18 ; CHECK: llihf 3, 1074340036
19 ; CHECK-NEXT: oilf 3, 2611340116
22 ; CHECK: stg 0, 2200(4)
23 define i64 @call_vararg_double1() {
25 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 3.141000e+00, double 2.718000e+00)
29 ; CHECK-LABEL: call_vararg_double2
32 ; CHECK: llihf 2, 1074118262
33 ; CHECK-NEXT: oilf 2, 3367254360
35 define i64 @call_vararg_double2() {
37 %retval = call i64 (i64, ...) @pass_vararg2(i64 8200, double 2.718000e+00)
41 ; CHECK-LABEL: call_vararg_double3
42 ; CHECK: llihf 0, 1072703839
43 ; CHECK-NEXT: oilf 0, 2861204133
44 ; CHECK: llihf 1, 1074118262
45 ; CHECK-NEXT: oilf 1, 3367254360
46 ; CHECK: llihf 2, 1074340036
47 ; CHECK-NEXT: oilf 2, 2611340116
48 ; CHECK: llihf 3, 1073127358
49 ; CHECK-NEXT: oilf 3, 1992864825
50 ; CHECK: stg 0, 2200(4)
51 define i64 @call_vararg_double3() {
53 %retval = call i64 (...) @pass_vararg3(double 2.718000e+00, double 3.141000e+00, double 1.414000e+00, double 1.010101e+00)
57 ; CHECK-LABEL: call_vararg_both0
60 define i64 @call_vararg_both0(i64 %arg0, double %arg1) {
61 %retval = call i64(...) @pass_vararg3(double %arg1, i64 %arg0)
65 ; CHECK-LABEL: call_vararg_long_double0
66 ; CHECK: larl 1, @CPI5_0
67 ; CHECK-NEXT: ld 0, 0(1)
68 ; CHECK-NEXT: ld 2, 8(1)
69 ; CHECK-NEXT: lgdr 3, 0
72 ; CHECK: std 0, 2192(4)
73 ; CHECK-NEXT: std 2, 2200(4)
74 define i64 @call_vararg_long_double0() {
76 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 0xLE0FC1518450562CD4000921FB5444261)
80 ; CHECK-LABEL: call_vararg_long_double1
84 ; CHECK: std 0, 2192(4)
85 ; CHECK-NEXT: std 2, 2200(4)
86 define i64 @call_vararg_long_double1(fp128 %arg0) {
88 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0)
92 ; CHECK-LABEL: call_vararg_long_double2
93 ; CHECK: std 4, 2208(4)
94 ; CHECK-NEXT: std 6, 2216(4)
98 ; CHECK: std 0, 2192(4)
99 ; CHECK-NEXT: std 2, 2200(4)
100 define i64 @call_vararg_long_double2(fp128 %arg0, fp128 %arg1) {
102 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0, fp128 %arg1)
106 ; CHECK-LABEL: call_vararg_long_double3
108 ; CHECK-NEXT: lgdr 2, 0
109 define i64 @call_vararg_long_double3(fp128 %arg0) {
111 %retval = call i64 (...) @pass_vararg3(fp128 %arg0)
115 ; ARCH12-LABEL: call_vec_vararg_test0
116 ; ARCH12: vlgvg 3, 24, 1
117 ; ARCH12: vlgvg 2, 24, 0
119 define void @call_vec_vararg_test0(<2 x double> %v) {
120 %retval = call i64(i64, ...) @pass_vararg2(i64 1, <2 x double> %v)
124 ; ARCH12-LABEL: call_vec_vararg_test1
125 ; ARCH12: larl 1, @CPI10_0
126 ; ARCH12: vl 0, 0(1), 3
127 ; ARCH12: vlgvg 3, 24, 0
128 ; ARCH12: vrepg 2, 0, 1
129 ; ARCH12: vst 25, 2208(4), 3
130 ; ARCH12: vst 24, 2192(4), 3
131 define void @call_vec_vararg_test1(<4 x i32> %v, <2 x i64> %w) {
132 %retval = call i64(fp128, ...) @pass_vararg1(fp128 0xLE0FC1518450562CD4000921FB5444261, <4 x i32> %v, <2 x i64> %w)
136 ; ARCH12-LABEL: call_vec_char_vararg_straddle
137 ; ARCH12: vlgvg 3, 24, 0
140 ; ARCH12: vst 24, 2192(4), 3
141 define void @call_vec_char_vararg_straddle(<16 x i8> %v) {
142 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <16 x i8> %v)
146 ; ARCH12-LABEL: call_vec_short_vararg_straddle
147 ; ARCH12: vlgvg 3, 24, 0
150 ; ARCH12: vst 24, 2192(4), 3
151 define void @call_vec_short_vararg_straddle(<8 x i16> %v) {
152 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <8 x i16> %v)
156 ; ARCH12-LABEL: call_vec_int_vararg_straddle
157 ; ARCH12: vlgvg 3, 24, 0
160 ; ARCH12: vst 24, 2192(4), 3
161 define void @call_vec_int_vararg_straddle(<4 x i32> %v) {
162 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <4 x i32> %v)
166 ; ARCH12-LABEL: call_vec_double_vararg_straddle
167 ; ARCH12: vlgvg 3, 24, 0
170 ; ARCH12: vst 24, 2192(4), 3
171 define void @call_vec_double_vararg_straddle(<2 x double> %v) {
172 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <2 x double> %v)
176 ; CHECK-LABEL: call_vararg_integral0
177 ; Since arguments 0, 1, and 2 are already in the correct
178 ; registers, we should have no loads of any sort into
186 define i64 @call_vararg_integral0(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) {
188 %retval = call i64(...) @pass_vararg3(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3)
192 ; Derived from C source:
193 ; #define _VARARG_EXT_
194 ; #include <stdarg.h>
196 ; long pass(long x, ...) {
199 ; long ret = va_arg(va, long);
204 ; CHECK-LABEL: pass_vararg:
205 ; CHECK: aghi 4, -160
206 ; CHECK: la 0, 2208(4)
207 ; CHECK: stg 0, 2200(4)
208 define hidden i64 @pass_vararg(i64 %x, ...) {
210 %va = alloca i8*, align 8
211 %va1 = bitcast i8** %va to i8*
212 call void @llvm.va_start(i8* %va1)
213 %argp.cur = load i8*, i8** %va, align 8
214 %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 8
215 store i8* %argp.next, i8** %va, align 8
216 %0 = bitcast i8* %argp.cur to i64*
217 %ret = load i64, i64* %0, align 8
218 %va2 = bitcast i8** %va to i8*
219 call void @llvm.va_end(i8* %va2)
223 declare void @llvm.va_start(i8*)
224 declare void @llvm.va_end(i8*)
226 declare i64 @pass_vararg0(i64 %arg0, i64 %arg1, ...)
227 declare i64 @pass_vararg1(fp128 %arg0, ...)
228 declare i64 @pass_vararg2(i64 %arg0, ...)
229 declare i64 @pass_vararg3(...)