; RUN: llc -mtriple=s390x-linux-gnu -mcpu=z13 -mattr=soft-float -O3 < %s | FileCheck %s
;
; Test that arguments and return values of fp/vector types are always handled
; with gprs with soft-float.
define double @f1(double %arg) {
; CHECK-LABEL: f1:
; CHECK-NOT: %r2
; CHECK-NOT: %{{[fv]}}
; CHECK: llihh %r3, 16368
; CHECK-NEXT: brasl %r14, __adddf3@PLT
; CHECK-NEXT: lmg %r14, %r15, 272(%r15)
; CHECK-NEXT: br %r14
%res = fadd double %arg, 1.0
ret double %res
}
define float @f2(float %arg) {
; CHECK-LABEL: f2:
; CHECK-NOT: %r2
; CHECK-NOT: %{{[fv]}}
; CHECK: llgfr %r2, %r2
; CHECK-NEXT: llilh %r3, 16256
; CHECK-NEXT: brasl %r14, __addsf3@PLT
; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
; CHECK-NEXT: lmg %r14, %r15, 272(%r15)
; CHECK-NEXT: br %r14
%res = fadd float %arg, 1.0
ret float %res
}
define fp128 @f2_fp128(fp128 %arg) {
; CHECK-LABEL: f2_fp128:
; CHECK-NOT: %{{[fv]}}
; CHECK: aghi %r15, -208
; CHECK-NEXT: .cfi_def_cfa_offset 368
; CHECK-NEXT: lg %r0, 0(%r2)
; CHECK-NEXT: lg %r1, 8(%r2)
; CHECK-NEXT: llihf %r2, 1073823744
; CHECK-NEXT: stg %r2, 160(%r15)
; CHECK-NEXT: la %r2, 192(%r15)
; CHECK-NEXT: la %r3, 176(%r15)
; CHECK-NEXT: la %r4, 160(%r15)
; CHECK-NEXT: stg %r1, 184(%r15)
; CHECK-NEXT: stg %r0, 176(%r15)
; CHECK-NEXT: mvghi 168(%r15), 0
; CHECK-NEXT: brasl %r14, __addtf3@PLT
; CHECK-NEXT: lg %r2, 192(%r15)
; CHECK-NEXT: lg %r3, 200(%r15)
; CHECK-NEXT: lmg %r14, %r15, 320(%r15)
; CHECK-NEXT: br %r14
%res = fadd fp128 %arg, 0xL00000000000000004001400000000000
ret fp128 %res
}
define <2 x double> @f3(<2 x double> %arg) {
; CHECK-LABEL: f3:
; CHECK-NOT: %{{[fv]}}
; CHECK: lg %r13, 8(%r2)
; CHECK-NEXT: lg %r2, 0(%r2)
; CHECK-NEXT: llihh %r3, 16368
; CHECK-NEXT: brasl %r14, __adddf3@PLT
; CHECK-NEXT: lgr %r12, %r2
; CHECK-NEXT: lgr %r2, %r13
; CHECK-NEXT: llihh %r3, 16368
; CHECK-NEXT: brasl %r14, __adddf3@PLT
; CHECK-NEXT: lgr %r3, %r2
; CHECK-NEXT: lgr %r2, %r12
; CHECK-NEXT: lmg %r12, %r15, 256(%r15)
; CHECK-NEXT: br %r14
%res = fadd <2 x double> %arg, <double 1.000000e+00, double 1.000000e+00>
ret <2 x double> %res
}
define <2 x float> @f4(<2 x float> %arg) {
; CHECK-LABEL: f4:
; CHECK-NOT: %{{[fv]}}
; CHECK: lr %r13, %r3
; CHECK-NEXT: llgfr %r2, %r2
; CHECK-NEXT: llilh %r3, 16256
; CHECK-NEXT: brasl %r14, __addsf3@PLT
; CHECK-NEXT: lgr %r12, %r2
; CHECK-NEXT: llgfr %r2, %r13
; CHECK-NEXT: llilh %r3, 16256
; CHECK-NEXT: brasl %r14, __addsf3@PLT
; CHECK-NEXT: lgr %r3, %r2
; CHECK-NEXT: lr %r2, %r12
; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d
; CHECK-NEXT: lmg %r12, %r15, 256(%r15)
; CHECK-NEXT: br %r14
%res = fadd <2 x float> %arg, <float 1.000000e+00, float 1.000000e+00>
ret <2 x float> %res
}
define <2 x i64> @f5(<2 x i64> %arg) {
; CHECK-LABEL: f5:
; CHECK-NOT: %{{[fv]}}
; CHECK: lghi %r0, 1
; CHECK-NEXT: ag %r0, 0(%r2)
; CHECK-NEXT: lghi %r3, 1
; CHECK-NEXT: ag %r3, 8(%r2)
; CHECK-NEXT: lgr %r2, %r0
; CHECK-NEXT: br %r14
%res = add <2 x i64> %arg, <i64 1, i64 1>
ret <2 x i64> %res
}
define <2 x i32> @f6(<2 x i32> %arg) {
; CHECK-LABEL: f6:
; CHECK-NOT: %{{[fv]}}
; CHECK: ahi %r2, 1
; CHECK-NEXT: ahi %r3, 1
; CHECK-NEXT: br %r14
%res = add <2 x i32> %arg, <i32 1, i32 1>
ret <2 x i32> %res
}
;; Stack arguments
define double @f7(double %A, double %B, double %C, double %D, double %E,
double %F) {
; CHECK-LABEL: f7:
; CHECK-NOT: %{{[fv]}}
; CHECK: aghi %r15, -160
; CHECK-NEXT: .cfi_def_cfa_offset 320
; CHECK-NEXT: lg %r3, 320(%r15)
; CHECK-NEXT: brasl %r14, __adddf3@PLT
; CHECK-NEXT: lmg %r14, %r15, 272(%r15)
; CHECK-NEXT: br %r14
%res = fadd double %A, %F
ret double %res
}
define float @f8(float %A, float %B, float %C, float %D, float %E,
float %F) {
; CHECK-LABEL: f8:
; CHECK-NOT: %{{[fv]}}
; CHECK: aghi %r15, -160
; CHECK-NEXT: .cfi_def_cfa_offset 320
; CHECK-NEXT: llgf %r3, 324(%r15)
; CHECK-NEXT: llgfr %r2, %r2
; CHECK-NEXT: brasl %r14, __addsf3@PLT
; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
; CHECK-NEXT: lmg %r14, %r15, 272(%r15)
; CHECK-NEXT: br %r14
%res = fadd float %A, %F
ret float %res
}
define <2 x double> @f9(<2 x double> %A, <2 x double> %B, <2 x double> %C,
<2 x double> %D, <2 x double> %E, <2 x double> %F,
<2 x double> %G, <2 x double> %H, <2 x double> %I) {
; CHECK-LABEL: f9:
; CHECK-NOT: %{{[fv]}}
; CHECK: aghi %r15, -160
; CHECK-NEXT: .cfi_def_cfa_offset 320
; CHECK-NEXT: lg %r1, 344(%r15)
; CHECK-NEXT: lg %r13, 8(%r2)
; CHECK-NEXT: lg %r2, 0(%r2)
; CHECK-NEXT: lg %r3, 0(%r1)
; CHECK-NEXT: lg %r12, 8(%r1)
; CHECK-NEXT: brasl %r14, __adddf3@PLT
; CHECK-NEXT: lgr %r11, %r2
; CHECK-NEXT: lgr %r2, %r13
; CHECK-NEXT: lgr %r3, %r12
; CHECK-NEXT: brasl %r14, __adddf3@PLT
; CHECK-NEXT: lgr %r3, %r2
; CHECK-NEXT: lgr %r2, %r11
; CHECK-NEXT: lmg %r11, %r15, 248(%r15)
; CHECK-NEXT: br %r14
%res = fadd <2 x double> %A, %I
ret <2 x double> %res
}
define <2 x float> @f10(<2 x float> %A, <2 x float> %B, <2 x float> %C,
<2 x float> %D, <2 x float> %E, <2 x float> %F,
<2 x float> %G, <2 x float> %H, <2 x float> %I) {
; CHECK-LABEL: f10:
; CHECK-NOT: %{{[fv]}}
; CHECK: aghi %r15, -160
; CHECK-NEXT: .cfi_def_cfa_offset 320
; CHECK-NEXT: lr %r13, %r3
; CHECK-NEXT: llgf %r3, 412(%r15)
; CHECK-NEXT: llgf %r12, 420(%r15)
; CHECK-NEXT: llgfr %r2, %r2
; CHECK-NEXT: brasl %r14, __addsf3@PLT
; CHECK-NEXT: lgr %r11, %r2
; CHECK-NEXT: llgfr %r2, %r13
; CHECK-NEXT: lgr %r3, %r12
; CHECK-NEXT: brasl %r14, __addsf3@PLT
; CHECK-NEXT: lgr %r3, %r2
; CHECK-NEXT: lr %r2, %r11
; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d
; CHECK-NEXT: lmg %r11, %r15, 248(%r15)
; CHECK-NEXT: br %r14
%res = fadd <2 x float> %A, %I
ret <2 x float> %res
}
define <2 x i64> @f11(<2 x i64> %A, <2 x i64> %B, <2 x i64> %C,
<2 x i64> %D, <2 x i64> %E, <2 x i64> %F,
<2 x i64> %G, <2 x i64> %H, <2 x i64> %I) {
; CHECK-LABEL: f11:
; CHECK-NOT: %{{[fv]}}
; CHECK: lg %r1, 184(%r15)
; CHECK-NEXT: lg %r3, 8(%r2)
; CHECK-NEXT: lg %r2, 0(%r2)
; CHECK-NEXT: ag %r2, 0(%r1)
; CHECK-NEXT: ag %r3, 8(%r1)
; CHECK-NEXT: br %r14
%res = add <2 x i64> %A, %I
ret <2 x i64> %res
}
;; calls
declare double @bar_double(double %arg);
define double @f12(double %arg, double %arg2) {
; CHECK-LABEL: f12:
; CHECK-NOT: %{{[fv]}}
; CHECK-NOT: %r{{[23]}}
; CHECK: lgr %r2, %r3
; CHECK-NEXT: brasl %r14, bar_double@PLT
; CHECK-NEXT: lmg %r14, %r15, 272(%r15)
; CHECK-NEXT: br %r14
%res = call double @bar_double(double %arg2)
ret double %res
}
declare float @bar_float(float %arg);
define float @f13(float %arg, float %arg2) {
; CHECK-LABEL: f13:
; CHECK-NOT: %{{[fv]}}
; CHECK-NOT: %r{{[23]}}
; CHECK: lr %r2, %r3
; CHECK-NEXT: brasl %r14, bar_float@PLT
; CHECK-NEXT: lmg %r14, %r15, 272(%r15)
; CHECK-NEXT: br %r14
%res = call float @bar_float(float %arg2)
ret float %res
}
declare fp128 @bar_fp128(fp128 %arg);
define fp128 @f14(fp128 %arg, fp128 %arg2) {
; CHECK-LABEL: f14:
; CHECK-NOT: %{{[fv]}}
; CHECK-NOT: %r3
; CHECK: lg %r0, 0(%r3)
; CHECK-NEXT: lg %r1, 8(%r3)
; CHECK-NEXT: la %r2, 160(%r15)
; CHECK-NEXT: stg %r1, 168(%r15)
; CHECK-NEXT: stg %r0, 160(%r15)
; CHECK-NEXT: brasl %r14, bar_fp128@PLT
; CHECK-NEXT: lmg %r14, %r15, 288(%r15)
; CHECK-NEXT: br %r14
%res = call fp128 @bar_fp128(fp128 %arg2)
ret fp128 %res
}
declare <2 x double> @bar_v2f64(<2 x double> %arg);
define <2 x double> @f15(<2 x double> %arg, <2 x double> %arg2) {
; CHECK-LABEL: f15:
; CHECK-NOT: %{{[fv]}}
; CHECK-NOT: %r3
; CHECK: lg %r0, 0(%r3)
; CHECK-NEXT: lg %r1, 8(%r3)
; CHECK-NEXT: la %r2, 160(%r15)
; CHECK-NEXT: stg %r1, 168(%r15)
; CHECK-NEXT: stg %r0, 160(%r15)
; CHECK-NEXT: brasl %r14, bar_v2f64@PLT
; CHECK-NEXT: lmg %r14, %r15, 288(%r15)
; CHECK-NEXT: br %r14
%res = call <2 x double> @bar_v2f64(<2 x double> %arg2)
ret <2 x double> %res
}
declare <2 x float> @bar_v2f32(<2 x float> %arg);
define <2 x float> @f16(<2 x float> %arg, <2 x float> %arg2) {
; CHECK-LABEL: f16:
; CHECK-NOT: %{{[fv]}}
; CHECK-NOT: %r{{[2345]}}
; CHECK: lr %r3, %r5
; CHECK-NEXT: lr %r2, %r4
; CHECK-NEXT: brasl %r14, bar_v2f32@PLT
; CHECK-NEXT: lmg %r14, %r15, 272(%r15)
; CHECK-NEXT: br %r14
%res = call <2 x float> @bar_v2f32(<2 x float> %arg2)
ret <2 x float> %res
}
declare <2 x i64> @bar_v2i64(<2 x i64> %arg);
define <2 x i64> @f17(<2 x i64> %arg, <2 x i64> %arg2) {
; CHECK-LABEL: f17:
; CHECK-NOT: %{{[fv]}}
; CHECK-NOT: %r3
; CHECK: lg %r0, 0(%r3)
; CHECK-NEXT: lg %r1, 8(%r3)
; CHECK-NEXT: la %r2, 160(%r15)
; CHECK-NEXT: stg %r1, 168(%r15)
; CHECK-NEXT: stg %r0, 160(%r15)
; CHECK-NEXT: brasl %r14, bar_v2i64@PLT
; CHECK-NEXT: lmg %r14, %r15, 288(%r15)
; CHECK-NEXT: br %r14
%res = call <2 x i64> @bar_v2i64(<2 x i64> %arg2)
ret <2 x i64> %res
}