[SystemZ] Fix expansion of ISD::FPOW and ISD::FSINCOS
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 21 Sep 2015 17:35:45 +0000 (17:35 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 21 Sep 2015 17:35:45 +0000 (17:35 +0000)
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

lib/Target/SystemZ/SystemZISelLowering.cpp
test/CodeGen/SystemZ/fp-libcall.ll [new file with mode: 0644]
test/CodeGen/SystemZ/fp-sincos-01.ll [new file with mode: 0644]

index 0e2bb5ebd2a9e6d4d643b7484735045e1b7bd9e1..9ef7ba248107d4a70af4d43e172eeaebe505ce92 100644 (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);
     }
   }
 
diff --git a/test/CodeGen/SystemZ/fp-libcall.ll b/test/CodeGen/SystemZ/fp-libcall.ll
new file mode 100644 (file)
index 0000000..75250b8
--- /dev/null
@@ -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)
+
diff --git a/test/CodeGen/SystemZ/fp-sincos-01.ll b/test/CodeGen/SystemZ/fp-sincos-01.ll
new file mode 100644 (file)
index 0000000..cd182a5
--- /dev/null
@@ -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
+