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
7; CHECK:       lghi  1, 1
8; CHECK:       lghi  2, 2
9define i64 @call_vararg_double0() {
10entry:
11  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 2.718000e+00)
12  ret i64 %retval
13}
14
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
20; CHECK:        lghi  1, 1
21; CHECK:        lghi  2, 2
22; CHECK:        stg 0, 2200(4)
23define i64 @call_vararg_double1() {
24entry:
25  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 3.141000e+00, double 2.718000e+00)
26  ret i64 %retval
27}
28
29; CHECK-LABEL: call_vararg_double2
30; CHECK-NOT:   llihf 0
31; CHECK-NOT:   oilf 0
32; CHECK:       llihf 2, 1074118262
33; CHECK-NEXT:  oilf  2, 3367254360
34; CHECK:       lghi  1, 8200
35define i64 @call_vararg_double2() {
36entry:
37  %retval = call i64 (i64, ...) @pass_vararg2(i64 8200, double 2.718000e+00)
38  ret i64 %retval
39}
40
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)
51define i64 @call_vararg_double3() {
52entry:
53  %retval = call i64 (...) @pass_vararg3(double 2.718000e+00, double 3.141000e+00, double 1.414000e+00, double 1.010101e+00)
54  ret i64 %retval
55}
56
57; CHECK-LABEL: call_vararg_both0
58; CHECK:       lgr   2, 1
59; CHECK:       lgdr  1, 0
60define i64 @call_vararg_both0(i64 %arg0, double %arg1) {
61  %retval  = call i64(...) @pass_vararg3(double %arg1, i64 %arg0)
62  ret i64 %retval
63}
64
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
70; CHECK:       lghi  1, 1
71; CHECK:       lghi  2, 2
72; CHECK:       std   0, 2192(4)
73; CHECK-NEXT:  std   2, 2200(4)
74define i64 @call_vararg_long_double0() {
75entry:
76  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 0xLE0FC1518450562CD4000921FB5444261)
77  ret i64 %retval
78}
79
80; CHECK-LABEL: call_vararg_long_double1
81; CHECK:       lgdr  3, 0
82; CHECK:       lghi  1, 1
83; CHECK:       lghi  2, 2
84; CHECK:       std   0, 2192(4)
85; CHECK-NEXT:  std   2, 2200(4)
86define i64 @call_vararg_long_double1(fp128 %arg0) {
87entry:
88  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0)
89  ret i64 %retval
90}
91
92; CHECK-LABEL: call_vararg_long_double2
93; CHECK:      std   4, 2208(4)
94; CHECK-NEXT: std   6, 2216(4)
95; CHECK:      lgdr  3, 0
96; CHECK:      lghi  1, 1
97; CHECK:      lghi  2, 2
98; CHECK:      std   0, 2192(4)
99; CHECK-NEXT: std   2, 2200(4)
100define i64 @call_vararg_long_double2(fp128 %arg0, fp128 %arg1) {
101entry:
102  %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0, fp128 %arg1)
103  ret i64 %retval
104}
105
106; CHECK-LABEL: call_vararg_long_double3
107; CHECK:       lgdr 3, 2
108; CHECK-NEXT:  lgdr 2, 0
109define i64 @call_vararg_long_double3(fp128 %arg0) {
110entry:
111  %retval = call i64 (...) @pass_vararg3(fp128 %arg0)
112  ret i64 %retval
113}
114
115; ARCH12-LABEL: call_vec_vararg_test0
116; ARCH12: vlgvg 3, 24, 1
117; ARCH12: vlgvg 2, 24, 0
118; ARCH12: lghi  1, 1
119define void @call_vec_vararg_test0(<2 x double> %v) {
120  %retval = call i64(i64, ...) @pass_vararg2(i64 1, <2 x double> %v)
121  ret void
122}
123
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
131define 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)
133  ret void
134}
135
136; ARCH12-LABEL: call_vec_char_vararg_straddle
137; ARCH12: vlgvg 3, 24, 0
138; ARCH12: lghi  1, 1
139; ARCH12: lghi  2, 2
140; ARCH12: vst   24, 2192(4), 3
141define 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)
143  ret void
144}
145
146; ARCH12-LABEL: call_vec_short_vararg_straddle
147; ARCH12: vlgvg 3, 24, 0
148; ARCH12: lghi  1, 1
149; ARCH12: lghi  2, 2
150; ARCH12: vst   24, 2192(4), 3
151define 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)
153  ret void
154}
155
156; ARCH12-LABEL: call_vec_int_vararg_straddle
157; ARCH12: vlgvg 3, 24, 0
158; ARCH12: lghi  1, 1
159; ARCH12: lghi  2, 2
160; ARCH12: vst 24, 2192(4), 3
161define 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)
163  ret void
164}
165
166; ARCH12-LABEL: call_vec_double_vararg_straddle
167; ARCH12: vlgvg 3, 24, 0
168; ARCH12: lghi  1, 1
169; ARCH12: lghi  2, 2
170; ARCH12: vst 24, 2192(4), 3
171define 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)
173  ret void
174}
175
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
179; GPRs 1, 2, and 3.
180; CHECK-NOT: lg  1
181; CHECK-NOT: lgr  1
182; CHECK-NOT: lg  2
183; CHECK-NOT: lgr  2
184; CHECK-NOT: lg  3
185; CHECK-NOT: lgr  3
186define i64 @call_vararg_integral0(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) {
187entry:
188  %retval = call i64(...) @pass_vararg3(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3)
189  ret i64 %retval
190}
191
192declare i64 @pass_vararg0(i64 %arg0, i64 %arg1, ...)
193declare i64 @pass_vararg1(fp128 %arg0, ...)
194declare i64 @pass_vararg2(i64 %arg0, ...)
195declare i64 @pass_vararg3(...)
196