[SystemZ] Fix expansion of ISD::FPOW and ISD::FSINCOS

The ISD::FPOW and ISD::FSINCOS opcodes default to Legal, but there
is no legal instruction for those on SystemZ.  This could cause
LLVM internal errors.  Fixed by setting the operation action to
Expand for those opcodes.

Also added test cases for all other LLVM IR intrinsics that should
generate a library call.  (Those already work correctly since the
default operation action is fine.)



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248180 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ulrich Weigand 2015-09-21 17:35:45 +00:00
parent 7d3733cd0d
commit eeec957a3d
3 changed files with 331 additions and 0 deletions

View File

@ -369,7 +369,9 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
// No special instructions for these.
setOperationAction(ISD::FSIN, VT, Expand);
setOperationAction(ISD::FCOS, VT, Expand);
setOperationAction(ISD::FSINCOS, VT, Expand);
setOperationAction(ISD::FREM, VT, Expand);
setOperationAction(ISD::FPOW, VT, Expand);
}
}

View File

@ -0,0 +1,273 @@
; Test that library calls are emitted for LLVM IR intrinsics
;
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
define float @f1(float %x, i32 %y) {
; CHECK-LABEL: f1:
; CHECK: brasl %r14, __powisf2@PLT
%tmp = call float @llvm.powi.f32(float %x, i32 %y)
ret float %tmp
}
define double @f2(double %x, i32 %y) {
; CHECK-LABEL: f2:
; CHECK: brasl %r14, __powidf2@PLT
%tmp = call double @llvm.powi.f64(double %x, i32 %y)
ret double %tmp
}
define fp128 @f3(fp128 %x, i32 %y) {
; CHECK-LABEL: f3:
; CHECK: brasl %r14, __powitf2@PLT
%tmp = call fp128 @llvm.powi.f128(fp128 %x, i32 %y)
ret fp128 %tmp
}
define float @f4(float %x, float %y) {
; CHECK-LABEL: f4:
; CHECK: brasl %r14, powf@PLT
%tmp = call float @llvm.pow.f32(float %x, float %y)
ret float %tmp
}
define double @f5(double %x, double %y) {
; CHECK-LABEL: f5:
; CHECK: brasl %r14, pow@PLT
%tmp = call double @llvm.pow.f64(double %x, double %y)
ret double %tmp
}
define fp128 @f6(fp128 %x, fp128 %y) {
; CHECK-LABEL: f6:
; CHECK: brasl %r14, powl@PLT
%tmp = call fp128 @llvm.pow.f128(fp128 %x, fp128 %y)
ret fp128 %tmp
}
define float @f7(float %x) {
; CHECK-LABEL: f7:
; CHECK: brasl %r14, sinf@PLT
%tmp = call float @llvm.sin.f32(float %x)
ret float %tmp
}
define double @f8(double %x) {
; CHECK-LABEL: f8:
; CHECK: brasl %r14, sin@PLT
%tmp = call double @llvm.sin.f64(double %x)
ret double %tmp
}
define fp128 @f9(fp128 %x) {
; CHECK-LABEL: f9:
; CHECK: brasl %r14, sinl@PLT
%tmp = call fp128 @llvm.sin.f128(fp128 %x)
ret fp128 %tmp
}
define float @f10(float %x) {
; CHECK-LABEL: f10:
; CHECK: brasl %r14, cosf@PLT
%tmp = call float @llvm.cos.f32(float %x)
ret float %tmp
}
define double @f11(double %x) {
; CHECK-LABEL: f11:
; CHECK: brasl %r14, cos@PLT
%tmp = call double @llvm.cos.f64(double %x)
ret double %tmp
}
define fp128 @f12(fp128 %x) {
; CHECK-LABEL: f12:
; CHECK: brasl %r14, cosl@PLT
%tmp = call fp128 @llvm.cos.f128(fp128 %x)
ret fp128 %tmp
}
define float @f13(float %x) {
; CHECK-LABEL: f13:
; CHECK: brasl %r14, expf@PLT
%tmp = call float @llvm.exp.f32(float %x)
ret float %tmp
}
define double @f14(double %x) {
; CHECK-LABEL: f14:
; CHECK: brasl %r14, exp@PLT
%tmp = call double @llvm.exp.f64(double %x)
ret double %tmp
}
define fp128 @f15(fp128 %x) {
; CHECK-LABEL: f15:
; CHECK: brasl %r14, expl@PLT
%tmp = call fp128 @llvm.exp.f128(fp128 %x)
ret fp128 %tmp
}
define float @f16(float %x) {
; CHECK-LABEL: f16:
; CHECK: brasl %r14, exp2f@PLT
%tmp = call float @llvm.exp2.f32(float %x)
ret float %tmp
}
define double @f17(double %x) {
; CHECK-LABEL: f17:
; CHECK: brasl %r14, exp2@PLT
%tmp = call double @llvm.exp2.f64(double %x)
ret double %tmp
}
define fp128 @f18(fp128 %x) {
; CHECK-LABEL: f18:
; CHECK: brasl %r14, exp2l@PLT
%tmp = call fp128 @llvm.exp2.f128(fp128 %x)
ret fp128 %tmp
}
define float @f19(float %x) {
; CHECK-LABEL: f19:
; CHECK: brasl %r14, logf@PLT
%tmp = call float @llvm.log.f32(float %x)
ret float %tmp
}
define double @f20(double %x) {
; CHECK-LABEL: f20:
; CHECK: brasl %r14, log@PLT
%tmp = call double @llvm.log.f64(double %x)
ret double %tmp
}
define fp128 @f21(fp128 %x) {
; CHECK-LABEL: f21:
; CHECK: brasl %r14, logl@PLT
%tmp = call fp128 @llvm.log.f128(fp128 %x)
ret fp128 %tmp
}
define float @f22(float %x) {
; CHECK-LABEL: f22:
; CHECK: brasl %r14, log2f@PLT
%tmp = call float @llvm.log2.f32(float %x)
ret float %tmp
}
define double @f23(double %x) {
; CHECK-LABEL: f23:
; CHECK: brasl %r14, log2@PLT
%tmp = call double @llvm.log2.f64(double %x)
ret double %tmp
}
define fp128 @f24(fp128 %x) {
; CHECK-LABEL: f24:
; CHECK: brasl %r14, log2l@PLT
%tmp = call fp128 @llvm.log2.f128(fp128 %x)
ret fp128 %tmp
}
define float @f25(float %x) {
; CHECK-LABEL: f25:
; CHECK: brasl %r14, log10f@PLT
%tmp = call float @llvm.log10.f32(float %x)
ret float %tmp
}
define double @f26(double %x) {
; CHECK-LABEL: f26:
; CHECK: brasl %r14, log10@PLT
%tmp = call double @llvm.log10.f64(double %x)
ret double %tmp
}
define fp128 @f27(fp128 %x) {
; CHECK-LABEL: f27:
; CHECK: brasl %r14, log10l@PLT
%tmp = call fp128 @llvm.log10.f128(fp128 %x)
ret fp128 %tmp
}
define float @f28(float %x, float %y) {
; CHECK-LABEL: f28:
; CHECK: brasl %r14, fminf@PLT
%tmp = call float @llvm.minnum.f32(float %x, float %y)
ret float %tmp
}
define double @f29(double %x, double %y) {
; CHECK-LABEL: f29:
; CHECK: brasl %r14, fmin@PLT
%tmp = call double @llvm.minnum.f64(double %x, double %y)
ret double %tmp
}
define fp128 @f30(fp128 %x, fp128 %y) {
; CHECK-LABEL: f30:
; CHECK: brasl %r14, fminl@PLT
%tmp = call fp128 @llvm.minnum.f128(fp128 %x, fp128 %y)
ret fp128 %tmp
}
define float @f31(float %x, float %y) {
; CHECK-LABEL: f31:
; CHECK: brasl %r14, fmaxf@PLT
%tmp = call float @llvm.maxnum.f32(float %x, float %y)
ret float %tmp
}
define double @f32(double %x, double %y) {
; CHECK-LABEL: f32:
; CHECK: brasl %r14, fmax@PLT
%tmp = call double @llvm.maxnum.f64(double %x, double %y)
ret double %tmp
}
define fp128 @f33(fp128 %x, fp128 %y) {
; CHECK-LABEL: f33:
; CHECK: brasl %r14, fmaxl@PLT
%tmp = call fp128 @llvm.maxnum.f128(fp128 %x, fp128 %y)
ret fp128 %tmp
}
declare float @llvm.powi.f32(float, i32)
declare double @llvm.powi.f64(double, i32)
declare fp128 @llvm.powi.f128(fp128, i32)
declare float @llvm.pow.f32(float, float)
declare double @llvm.pow.f64(double, double)
declare fp128 @llvm.pow.f128(fp128, fp128)
declare float @llvm.sin.f32(float)
declare double @llvm.sin.f64(double)
declare fp128 @llvm.sin.f128(fp128)
declare float @llvm.cos.f32(float)
declare double @llvm.cos.f64(double)
declare fp128 @llvm.cos.f128(fp128)
declare float @llvm.exp.f32(float)
declare double @llvm.exp.f64(double)
declare fp128 @llvm.exp.f128(fp128)
declare float @llvm.exp2.f32(float)
declare double @llvm.exp2.f64(double)
declare fp128 @llvm.exp2.f128(fp128)
declare float @llvm.log.f32(float)
declare double @llvm.log.f64(double)
declare fp128 @llvm.log.f128(fp128)
declare float @llvm.log2.f32(float)
declare double @llvm.log2.f64(double)
declare fp128 @llvm.log2.f128(fp128)
declare float @llvm.log10.f32(float)
declare double @llvm.log10.f64(double)
declare fp128 @llvm.log10.f128(fp128)
declare float @llvm.minnum.f32(float, float)
declare double @llvm.minnum.f64(double, double)
declare fp128 @llvm.minnum.f128(fp128, fp128)
declare float @llvm.maxnum.f32(float, float)
declare double @llvm.maxnum.f64(double, double)
declare fp128 @llvm.maxnum.f128(fp128, fp128)

View File

@ -0,0 +1,56 @@
; Test that combined sin/cos library call is emitted when appropriate
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=CHECK-NOOPT
; RUN: llc < %s -mtriple=s390x-linux-gnu -enable-unsafe-fp-math | FileCheck %s --check-prefix=CHECK-OPT
define float @f1(float %x) {
; CHECK-OPT-LABEL: f1:
; CHECK-OPT: brasl %r14, sincosf@PLT
; CHECK-OPT: le %f0, 164(%r15)
; CHECK-OPT: aeb %f0, 160(%r15)
; CHECK-NOOPT-LABEL: f1:
; CHECK-NOOPT: brasl %r14, sinf@PLT
; CHECK-NOOPT: brasl %r14, cosf@PLT
%tmp1 = call float @sinf(float %x)
%tmp2 = call float @cosf(float %x)
%add = fadd float %tmp1, %tmp2
ret float %add
}
define double @f2(double %x) {
; CHECK-OPT-LABEL: f2:
; CHECK-OPT: brasl %r14, sincos@PLT
; CHECK-OPT: ld %f0, 168(%r15)
; CHECK-OPT: adb %f0, 160(%r15)
; CHECK-NOOPT-LABEL: f2:
; CHECK-NOOPT: brasl %r14, sin@PLT
; CHECK-NOOPT: brasl %r14, cos@PLT
%tmp1 = call double @sin(double %x)
%tmp2 = call double @cos(double %x)
%add = fadd double %tmp1, %tmp2
ret double %add
}
define fp128 @f3(fp128 %x) {
; CHECK-OPT-LABEL: f3:
; CHECK-OPT: brasl %r14, sincosl@PLT
; CHECK-OPT: axbr
; CHECK-NOOPT-LABEL: f3:
; CHECK-NOOPT: brasl %r14, sinl@PLT
; CHECK-NOOPT: brasl %r14, cosl@PLT
%tmp1 = call fp128 @sinl(fp128 %x)
%tmp2 = call fp128 @cosl(fp128 %x)
%add = fadd fp128 %tmp1, %tmp2
ret fp128 %add
}
declare float @sinf(float) readonly
declare double @sin(double) readonly
declare fp128 @sinl(fp128) readonly
declare float @cosf(float) readonly
declare double @cos(double) readonly
declare fp128 @cosl(fp128) readonly