1; RUN: llc -mtriple=s390x-linux-gnu -mcpu=z13 -mattr=soft-float -O3 < %s | FileCheck %s
2;
3; Test that arguments and return values of fp/vector types are always handled
4; with gprs with soft-float.
5
6define double @f1(double %arg) {
7; CHECK-LABEL: f1:
8; CHECK-NOT: %r2
9; CHECK-NOT: %{{[fv]}}
10; CHECK: llihh %r3, 16368
11; CHECK-NEXT: brasl %r14, __adddf3@PLT
12; CHECK-NEXT: lmg   %r14, %r15, 272(%r15)
13; CHECK-NEXT: br    %r14
14  %res = fadd double %arg, 1.0
15  ret double %res
16}
17
18define float @f2(float %arg) {
19; CHECK-LABEL: f2:
20; CHECK-NOT: %r2
21; CHECK-NOT: %{{[fv]}}
22; CHECK: llgfr   %r2, %r2
23; CHECK-NEXT: llilh   %r3, 16256
24; CHECK-NEXT: brasl   %r14, __addsf3@PLT
25; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
26; CHECK-NEXT: lmg     %r14, %r15, 272(%r15)
27; CHECK-NEXT: br      %r14
28  %res = fadd float %arg, 1.0
29  ret float %res
30}
31
32define fp128 @f2_fp128(fp128 %arg) {
33; CHECK-LABEL: f2_fp128:
34; CHECK-NOT: %{{[fv]}}
35; CHECK: aghi    %r15, -208
36; CHECK-NEXT: .cfi_def_cfa_offset 368
37; CHECK-NEXT: lg      %r0, 0(%r2)
38; CHECK-NEXT: lg      %r1, 8(%r2)
39; CHECK-NEXT: llihf   %r2, 1073823744
40; CHECK-NEXT: stg     %r2, 160(%r15)
41; CHECK-NEXT: la      %r2, 192(%r15)
42; CHECK-NEXT: la      %r3, 176(%r15)
43; CHECK-NEXT: la      %r4, 160(%r15)
44; CHECK-NEXT: stg     %r1, 184(%r15)
45; CHECK-NEXT: stg     %r0, 176(%r15)
46; CHECK-NEXT: mvghi   168(%r15), 0
47; CHECK-NEXT: brasl   %r14, __addtf3@PLT
48; CHECK-NEXT: lg      %r2, 192(%r15)
49; CHECK-NEXT: lg      %r3, 200(%r15)
50; CHECK-NEXT: lmg     %r14, %r15, 320(%r15)
51; CHECK-NEXT: br      %r14
52  %res = fadd fp128 %arg, 0xL00000000000000004001400000000000
53  ret fp128 %res
54}
55
56define <2 x double> @f3(<2 x double> %arg) {
57; CHECK-LABEL: f3:
58; CHECK-NOT: %{{[fv]}}
59; CHECK: lg      %r13, 8(%r2)
60; CHECK-NEXT: lg      %r2, 0(%r2)
61; CHECK-NEXT: llihh   %r3, 16368
62; CHECK-NEXT: brasl   %r14, __adddf3@PLT
63; CHECK-NEXT: lgr     %r12, %r2
64; CHECK-NEXT: lgr     %r2, %r13
65; CHECK-NEXT: llihh   %r3, 16368
66; CHECK-NEXT: brasl   %r14, __adddf3@PLT
67; CHECK-NEXT: lgr     %r3, %r2
68; CHECK-NEXT: lgr     %r2, %r12
69; CHECK-NEXT: lmg     %r12, %r15, 256(%r15)
70; CHECK-NEXT: br      %r14
71  %res = fadd <2 x double> %arg, <double 1.000000e+00, double 1.000000e+00>
72  ret <2 x double> %res
73}
74
75define <2 x float> @f4(<2 x float> %arg) {
76; CHECK-LABEL: f4:
77; CHECK-NOT: %{{[fv]}}
78; CHECK: lr      %r13, %r3
79; CHECK-NEXT: llgfr   %r2, %r2
80; CHECK-NEXT: llilh   %r3, 16256
81; CHECK-NEXT: brasl   %r14, __addsf3@PLT
82; CHECK-NEXT: lgr     %r12, %r2
83; CHECK-NEXT: llgfr   %r2, %r13
84; CHECK-NEXT: llilh   %r3, 16256
85; CHECK-NEXT: brasl   %r14, __addsf3@PLT
86; CHECK-NEXT: lgr     %r3, %r2
87; CHECK-NEXT: lr      %r2, %r12
88; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d
89; CHECK-NEXT: lmg     %r12, %r15, 256(%r15)
90; CHECK-NEXT: br      %r14
91  %res = fadd <2 x float> %arg, <float 1.000000e+00, float 1.000000e+00>
92  ret <2 x float> %res
93}
94
95define <2 x i64> @f5(<2 x i64> %arg) {
96; CHECK-LABEL: f5:
97; CHECK-NOT: %{{[fv]}}
98; CHECK: lghi    %r0, 1
99; CHECK-NEXT: ag      %r0, 0(%r2)
100; CHECK-NEXT: lghi    %r3, 1
101; CHECK-NEXT: ag      %r3, 8(%r2)
102; CHECK-NEXT: lgr     %r2, %r0
103; CHECK-NEXT: br      %r14
104  %res = add <2 x i64> %arg, <i64 1, i64 1>
105  ret <2 x i64> %res
106}
107
108define <2 x i32> @f6(<2 x i32> %arg) {
109; CHECK-LABEL: f6:
110; CHECK-NOT: %{{[fv]}}
111; CHECK: ahi     %r2, 1
112; CHECK-NEXT: ahi     %r3, 1
113; CHECK-NEXT: br      %r14
114  %res = add <2 x i32> %arg, <i32 1, i32 1>
115  ret <2 x i32> %res
116}
117
118;; Stack arguments
119
120define double @f7(double %A, double %B, double %C, double %D, double %E,
121                  double %F) {
122; CHECK-LABEL: f7:
123; CHECK-NOT: %{{[fv]}}
124; CHECK: aghi    %r15, -160
125; CHECK-NEXT: .cfi_def_cfa_offset 320
126; CHECK-NEXT: lg      %r3, 320(%r15)
127; CHECK-NEXT: brasl   %r14, __adddf3@PLT
128; CHECK-NEXT: lmg     %r14, %r15, 272(%r15)
129; CHECK-NEXT: br      %r14
130
131  %res = fadd double %A, %F
132  ret double %res
133}
134
135define float @f8(float %A, float %B, float %C, float %D, float %E,
136                 float %F) {
137; CHECK-LABEL: f8:
138; CHECK-NOT: %{{[fv]}}
139; CHECK: aghi    %r15, -160
140; CHECK-NEXT: .cfi_def_cfa_offset 320
141; CHECK-NEXT: llgf    %r3, 324(%r15)
142; CHECK-NEXT: llgfr   %r2, %r2
143; CHECK-NEXT: brasl   %r14, __addsf3@PLT
144; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
145; CHECK-NEXT: lmg     %r14, %r15, 272(%r15)
146; CHECK-NEXT: br      %r14
147  %res = fadd float %A, %F
148  ret float %res
149}
150
151define <2 x double> @f9(<2 x double> %A, <2 x double> %B, <2 x double> %C,
152                        <2 x double> %D, <2 x double> %E, <2 x double> %F,
153                        <2 x double> %G, <2 x double> %H, <2 x double> %I) {
154; CHECK-LABEL: f9:
155; CHECK-NOT: %{{[fv]}}
156; CHECK: aghi    %r15, -160
157; CHECK-NEXT: .cfi_def_cfa_offset 320
158; CHECK-NEXT: lg      %r1, 344(%r15)
159; CHECK-NEXT: lg      %r13, 8(%r2)
160; CHECK-NEXT: lg      %r2, 0(%r2)
161; CHECK-NEXT: lg      %r3, 0(%r1)
162; CHECK-NEXT: lg      %r12, 8(%r1)
163; CHECK-NEXT: brasl   %r14, __adddf3@PLT
164; CHECK-NEXT: lgr     %r11, %r2
165; CHECK-NEXT: lgr     %r2, %r13
166; CHECK-NEXT: lgr     %r3, %r12
167; CHECK-NEXT: brasl   %r14, __adddf3@PLT
168; CHECK-NEXT: lgr     %r3, %r2
169; CHECK-NEXT: lgr     %r2, %r11
170; CHECK-NEXT: lmg     %r11, %r15, 248(%r15)
171; CHECK-NEXT: br      %r14
172  %res = fadd <2 x double> %A, %I
173  ret <2 x double> %res
174}
175
176define <2 x float> @f10(<2 x float> %A, <2 x float> %B, <2 x float> %C,
177                        <2 x float> %D, <2 x float> %E, <2 x float> %F,
178                        <2 x float> %G, <2 x float> %H, <2 x float> %I) {
179; CHECK-LABEL: f10:
180; CHECK-NOT: %{{[fv]}}
181; CHECK: aghi    %r15, -160
182; CHECK-NEXT: .cfi_def_cfa_offset 320
183; CHECK-NEXT: lr      %r13, %r3
184; CHECK-NEXT: llgf    %r3, 412(%r15)
185; CHECK-NEXT: llgf    %r12, 420(%r15)
186; CHECK-NEXT: llgfr   %r2, %r2
187; CHECK-NEXT: brasl   %r14, __addsf3@PLT
188; CHECK-NEXT: lgr     %r11, %r2
189; CHECK-NEXT: llgfr   %r2, %r13
190; CHECK-NEXT: lgr     %r3, %r12
191; CHECK-NEXT: brasl   %r14, __addsf3@PLT
192; CHECK-NEXT: lgr     %r3, %r2
193; CHECK-NEXT: lr      %r2, %r11
194; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d
195; CHECK-NEXT: lmg     %r11, %r15, 248(%r15)
196; CHECK-NEXT: br      %r14
197
198  %res = fadd <2 x float> %A, %I
199  ret <2 x float> %res
200}
201
202define <2 x i64> @f11(<2 x i64> %A, <2 x i64> %B, <2 x i64> %C,
203                      <2 x i64> %D, <2 x i64> %E, <2 x i64> %F,
204                      <2 x i64> %G, <2 x i64> %H, <2 x i64> %I) {
205; CHECK-LABEL: f11:
206; CHECK-NOT: %{{[fv]}}
207; CHECK: lg      %r1, 184(%r15)
208; CHECK-NEXT: lg      %r3, 8(%r2)
209; CHECK-NEXT: lg      %r2, 0(%r2)
210; CHECK-NEXT: ag      %r2, 0(%r1)
211; CHECK-NEXT: ag      %r3, 8(%r1)
212; CHECK-NEXT: br      %r14
213  %res = add <2 x i64> %A, %I
214  ret <2 x i64> %res
215}
216
217;; calls
218
219declare double @bar_double(double %arg);
220define double @f12(double %arg, double %arg2) {
221; CHECK-LABEL: f12:
222; CHECK-NOT: %{{[fv]}}
223; CHECK-NOT: %r{{[23]}}
224; CHECK: lgr     %r2, %r3
225; CHECK-NEXT: brasl   %r14, bar_double@PLT
226; CHECK-NEXT: lmg     %r14, %r15, 272(%r15)
227; CHECK-NEXT: br      %r14
228  %res = call double @bar_double(double %arg2)
229  ret double %res
230}
231
232declare float @bar_float(float %arg);
233define float @f13(float %arg, float %arg2) {
234; CHECK-LABEL: f13:
235; CHECK-NOT: %{{[fv]}}
236; CHECK-NOT: %r{{[23]}}
237; CHECK: lr     %r2, %r3
238; CHECK-NEXT: brasl   %r14, bar_float@PLT
239; CHECK-NEXT: lmg     %r14, %r15, 272(%r15)
240; CHECK-NEXT: br      %r14
241  %res = call float @bar_float(float %arg2)
242  ret float %res
243}
244
245declare fp128 @bar_fp128(fp128 %arg);
246define fp128 @f14(fp128 %arg, fp128 %arg2) {
247; CHECK-LABEL: f14:
248; CHECK-NOT: %{{[fv]}}
249; CHECK-NOT: %r3
250; CHECK: lg      %r0, 0(%r3)
251; CHECK-NEXT: lg      %r1, 8(%r3)
252; CHECK-NEXT: la      %r2, 160(%r15)
253; CHECK-NEXT: stg     %r1, 168(%r15)
254; CHECK-NEXT: stg     %r0, 160(%r15)
255; CHECK-NEXT: brasl   %r14, bar_fp128@PLT
256; CHECK-NEXT: lmg     %r14, %r15, 288(%r15)
257; CHECK-NEXT: br      %r14
258  %res = call fp128 @bar_fp128(fp128 %arg2)
259  ret fp128 %res
260}
261
262declare <2 x double> @bar_v2f64(<2 x double> %arg);
263define <2 x double> @f15(<2 x double> %arg, <2 x double> %arg2) {
264; CHECK-LABEL: f15:
265; CHECK-NOT: %{{[fv]}}
266; CHECK-NOT: %r3
267; CHECK: lg      %r0, 0(%r3)
268; CHECK-NEXT: lg      %r1, 8(%r3)
269; CHECK-NEXT: la      %r2, 160(%r15)
270; CHECK-NEXT: stg     %r1, 168(%r15)
271; CHECK-NEXT: stg     %r0, 160(%r15)
272; CHECK-NEXT: brasl   %r14, bar_v2f64@PLT
273; CHECK-NEXT: lmg     %r14, %r15, 288(%r15)
274; CHECK-NEXT: br      %r14
275  %res = call <2 x double> @bar_v2f64(<2 x double> %arg2)
276  ret <2 x double> %res
277}
278
279declare <2 x float> @bar_v2f32(<2 x float> %arg);
280define <2 x float> @f16(<2 x float> %arg, <2 x float> %arg2) {
281; CHECK-LABEL: f16:
282; CHECK-NOT: %{{[fv]}}
283; CHECK-NOT: %r{{[2345]}}
284; CHECK: lr      %r3, %r5
285; CHECK-NEXT: lr      %r2, %r4
286; CHECK-NEXT: brasl   %r14, bar_v2f32@PLT
287; CHECK-NEXT: lmg     %r14, %r15, 272(%r15)
288; CHECK-NEXT: br      %r14
289  %res = call <2 x float> @bar_v2f32(<2 x float> %arg2)
290  ret <2 x float> %res
291}
292
293declare <2 x i64> @bar_v2i64(<2 x i64> %arg);
294define <2 x i64> @f17(<2 x i64> %arg, <2 x i64> %arg2) {
295; CHECK-LABEL: f17:
296; CHECK-NOT: %{{[fv]}}
297; CHECK-NOT: %r3
298; CHECK: lg      %r0, 0(%r3)
299; CHECK-NEXT: lg      %r1, 8(%r3)
300; CHECK-NEXT: la      %r2, 160(%r15)
301; CHECK-NEXT: stg     %r1, 168(%r15)
302; CHECK-NEXT: stg     %r0, 160(%r15)
303; CHECK-NEXT: brasl   %r14, bar_v2i64@PLT
304; CHECK-NEXT: lmg     %r14, %r15, 288(%r15)
305; CHECK-NEXT: br      %r14
306  %res = call <2 x i64> @bar_v2i64(<2 x i64> %arg2)
307  ret <2 x i64> %res
308}
309