From 317096ab3710fda0960be58804e9f80c800340f6 Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Fri, 28 Sep 2007 01:08:20 +0000 Subject: [PATCH] Add sqrt and powi intrinsics for long double. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42423 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/RuntimeLibcalls.h | 6 ++- include/llvm/Intrinsics.td | 10 ++++ lib/Analysis/ConstantFolding.cpp | 6 +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 17 ++++--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 6 +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp | 2 + test/CodeGen/X86/2007-09-27-LDIntrinsics.ll | 47 +++++++++++++++++++ utils/TableGen/CodeGenTarget.cpp | 2 + utils/TableGen/IntrinsicEmitter.cpp | 6 +++ 9 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 test/CodeGen/X86/2007-09-27-LDIntrinsics.ll diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 0b36c6dd28f..80cc33a0bc7 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -18,7 +18,9 @@ namespace llvm { namespace RTLIB { /// RTLIB::Libcall enum - This enum defines all of the runtime library calls - /// the backend can emit. + /// the backend can emit. "LD" is used for all long double types, since + /// these functions will have the same interface on different targets even + /// though the data is not in the same format. /// enum Libcall { // Integer @@ -56,8 +58,10 @@ namespace RTLIB { NEG_F64, POWI_F32, POWI_F64, + POWI_LD, SQRT_F32, SQRT_F64, + SQRT_LD, SIN_F32, SIN_F64, COS_F32, diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 9d3b1804faf..4b1e419d651 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -76,6 +76,9 @@ def llvm_i32_ty : LLVMType; def llvm_i64_ty : LLVMType; def llvm_float_ty : LLVMType; def llvm_double_ty : LLVMType; +def llvm_f80_ty : LLVMType; +def llvm_f128_ty : LLVMType; +def llvm_ppcf128_ty : LLVMType; def llvm_ptr_ty : LLVMPointerType; // i8* def llvm_ptrptr_ty : LLVMPointerType; // i8** def llvm_empty_ty : LLVMType; // { } @@ -177,9 +180,16 @@ let Properties = [IntrWriteArgMem] in { let Properties = [IntrNoMem] in { def int_sqrt_f32 : Intrinsic<[llvm_float_ty, llvm_float_ty]>; def int_sqrt_f64 : Intrinsic<[llvm_double_ty, llvm_double_ty]>; + def int_sqrt_f80 : Intrinsic<[llvm_f80_ty, llvm_f80_ty]>; + def int_sqrt_f128 : Intrinsic<[llvm_f128_ty, llvm_f128_ty]>; + def int_sqrt_ppcf128 : Intrinsic<[llvm_ppcf128_ty, llvm_ppcf128_ty]>; def int_powi_f32 : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_i32_ty]>; def int_powi_f64 : Intrinsic<[llvm_double_ty, llvm_double_ty, llvm_i32_ty]>; + def int_powi_f80 : Intrinsic<[llvm_f80_ty, llvm_f80_ty, llvm_i32_ty]>; + def int_powi_f128 : Intrinsic<[llvm_f128_ty, llvm_f128_ty, llvm_i32_ty]>; + def int_powi_ppcf128 : Intrinsic<[llvm_ppcf128_ty, llvm_ppcf128_ty, + llvm_i32_ty]>; } // NOTE: these are internal interfaces. diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 6c828fa0042..d68961580ec 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -331,8 +331,14 @@ llvm::canConstantFoldCallTo(Function *F) { switch (F->getIntrinsicID()) { case Intrinsic::sqrt_f32: case Intrinsic::sqrt_f64: + case Intrinsic::sqrt_f80: + case Intrinsic::sqrt_f128: + case Intrinsic::sqrt_ppcf128: case Intrinsic::powi_f32: case Intrinsic::powi_f64: + case Intrinsic::powi_f80: + case Intrinsic::powi_f128: + case Intrinsic::powi_ppcf128: case Intrinsic::bswap: case Intrinsic::ctpop: case Intrinsic::ctlz: diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 509e2252f6f..b976195847f 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -3044,7 +3044,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; switch(Node->getOpcode()) { case ISD::FSQRT: - LC = VT == MVT::f32 ? RTLIB::SQRT_F32 : RTLIB::SQRT_F64; + LC = VT == MVT::f32 ? RTLIB::SQRT_F32 : + VT == MVT::f64 ? RTLIB::SQRT_F64 : RTLIB::SQRT_LD; break; case ISD::FSIN: LC = VT == MVT::f32 ? RTLIB::SIN_F32 : RTLIB::SIN_F64; @@ -3065,8 +3066,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; case ISD::FPOWI: { // We always lower FPOWI into a libcall. No target support it yet. - RTLIB::Libcall LC = Node->getValueType(0) == MVT::f32 - ? RTLIB::POWI_F32 : RTLIB::POWI_F64; + RTLIB::Libcall LC = + Node->getValueType(0) == MVT::f32 ? RTLIB::POWI_F32 : + Node->getValueType(0) == MVT::f64 ? RTLIB::POWI_F64 : + RTLIB::POWI_LD; SDOperand Dummy; Result = ExpandLibCall(TLI.getLibcallName(LC), Node, false/*sign irrelevant*/, Dummy); @@ -5688,8 +5691,9 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){ Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::FPROUND_F64_F32),Node,true,Hi); break; case ISD::FPOWI: - Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32) - ? RTLIB::POWI_F32 : RTLIB::POWI_F64), + Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32) ? RTLIB::POWI_F32 : + (VT == MVT::f64) ? RTLIB::POWI_F64 : + RTLIB::POWI_LD), Node, false, Hi); break; case ISD::FSQRT: @@ -5698,7 +5702,8 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; switch(Node->getOpcode()) { case ISD::FSQRT: - LC = (VT == MVT::f32) ? RTLIB::SQRT_F32 : RTLIB::SQRT_F64; + LC = (VT == MVT::f32) ? RTLIB::SQRT_F32 : + (VT == MVT::f64) ? RTLIB::SQRT_F64 : RTLIB::SQRT_LD; break; case ISD::FSIN: LC = (VT == MVT::f32) ? RTLIB::SIN_F32 : RTLIB::SIN_F64; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index f582c8f1d72..23ad28f33b1 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2798,12 +2798,18 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::sqrt_f32: case Intrinsic::sqrt_f64: + case Intrinsic::sqrt_f80: + case Intrinsic::sqrt_f128: + case Intrinsic::sqrt_ppcf128: setValue(&I, DAG.getNode(ISD::FSQRT, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1)))); return 0; case Intrinsic::powi_f32: case Intrinsic::powi_f64: + case Intrinsic::powi_f80: + case Intrinsic::powi_f128: + case Intrinsic::powi_ppcf128: setValue(&I, DAG.getNode(ISD::FPOWI, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1)), diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 0898173ef9e..f87ebe40a12 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -58,8 +58,10 @@ static void InitLibcallNames(const char **Names) { Names[RTLIB::NEG_F64] = "__negdf2"; Names[RTLIB::POWI_F32] = "__powisf2"; Names[RTLIB::POWI_F64] = "__powidf2"; + Names[RTLIB::POWI_LD] = "__powixf2"; Names[RTLIB::SQRT_F32] = "sqrtf"; Names[RTLIB::SQRT_F64] = "sqrt"; + Names[RTLIB::SQRT_LD] = "sqrtl"; Names[RTLIB::SIN_F32] = "sinf"; Names[RTLIB::SIN_F64] = "sin"; Names[RTLIB::COS_F32] = "cosf"; diff --git a/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll b/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll new file mode 100644 index 00000000000..be51c04a383 --- /dev/null +++ b/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll @@ -0,0 +1,47 @@ +; RUN: llvm-as < %s | llc | grep powixf2 +; RUN: llvm-as < %s | llc | grep fsqrt +; ModuleID = 'yyy.c' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i686-apple-darwin8" + +define x86_fp80 @foo(x86_fp80 %x) { +entry: + %x_addr = alloca x86_fp80 ; [#uses=2] + %retval = alloca x86_fp80 ; [#uses=2] + %tmp = alloca x86_fp80 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store x86_fp80 %x, x86_fp80* %x_addr + %tmp1 = load x86_fp80* %x_addr, align 16 ; [#uses=1] + %tmp2 = call x86_fp80 @llvm.sqrt.f80( x86_fp80 %tmp1 ) ; [#uses=1] + store x86_fp80 %tmp2, x86_fp80* %tmp, align 16 + %tmp3 = load x86_fp80* %tmp, align 16 ; [#uses=1] + store x86_fp80 %tmp3, x86_fp80* %retval, align 16 + br label %return + +return: ; preds = %entry + %retval4 = load x86_fp80* %retval ; [#uses=1] + ret x86_fp80 %retval4 +} + +declare x86_fp80 @llvm.sqrt.f80(x86_fp80) + +define x86_fp80 @bar(x86_fp80 %x) { +entry: + %x_addr = alloca x86_fp80 ; [#uses=2] + %retval = alloca x86_fp80 ; [#uses=2] + %tmp = alloca x86_fp80 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store x86_fp80 %x, x86_fp80* %x_addr + %tmp1 = load x86_fp80* %x_addr, align 16 ; [#uses=1] + %tmp2 = call x86_fp80 @llvm.powi.f80( x86_fp80 %tmp1, i32 3 ) ; [#uses=1] + store x86_fp80 %tmp2, x86_fp80* %tmp, align 16 + %tmp3 = load x86_fp80* %tmp, align 16 ; [#uses=1] + store x86_fp80 %tmp3, x86_fp80* %retval, align 16 + br label %return + +return: ; preds = %entry + %retval4 = load x86_fp80* %retval ; [#uses=1] + ret x86_fp80 %retval4 +} + +declare x86_fp80 @llvm.powi.f80(x86_fp80, i32) diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index c73ffb98ef1..ea96cf4bd27 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -49,6 +49,7 @@ std::string llvm::getName(MVT::ValueType T) { case MVT::f64: return "MVT::f64"; case MVT::f80: return "MVT::f80"; case MVT::f128: return "MVT::f128"; + case MVT::ppcf128: return "MVT::ppcf128"; case MVT::Flag: return "MVT::Flag"; case MVT::isVoid:return "MVT::void"; case MVT::v8i8: return "MVT::v8i8"; @@ -84,6 +85,7 @@ std::string llvm::getEnumName(MVT::ValueType T) { case MVT::f64: return "MVT::f64"; case MVT::f80: return "MVT::f80"; case MVT::f128: return "MVT::f128"; + case MVT::ppcf128: return "MVT::ppcf128"; case MVT::Flag: return "MVT::Flag"; case MVT::isVoid:return "MVT::isVoid"; case MVT::v8i8: return "MVT::v8i8"; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index c3db273ce60..b7c8093875c 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -131,6 +131,12 @@ static void EmitTypeForValueType(std::ostream &OS, MVT::ValueType VT) { OS << "Type::FloatTy"; } else if (VT == MVT::f64) { OS << "Type::DoubleTy"; + } else if (VT == MVT::f80) { + OS << "Type::X86_FP80Ty"; + } else if (VT == MVT::f128) { + OS << "Type::FP128Ty"; + } else if (VT == MVT::ppcf128) { + OS << "Type::PPC_FP128Ty"; } else if (VT == MVT::isVoid) { OS << "Type::VoidTy"; } else { -- 2.34.1