From: Qiu Chaofan Date: Wed, 3 Nov 2021 09:57:25 +0000 (+0800) Subject: [PowerPC] Implement longdouble pack/unpack builtins X-Git-Tag: upstream/15.0.7~26849 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=741aeda97d6327edd9905b21a5308fcee21bbefd;p=platform%2Fupstream%2Fllvm.git [PowerPC] Implement longdouble pack/unpack builtins Implement two builtins to pack/unpack IBM extended long double float, according to GCC 'Basic PowerPC Builtin Functions Available ISA 2.05'. Reviewed By: jsji Differential Revision: https://reviews.llvm.org/D112055 --- diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def index f82d455..cd6b2df 100644 --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -780,6 +780,10 @@ BUILTIN(__builtin_cfuged, "ULLiULLiULLi", "") BUILTIN(__builtin_cntlzdm, "ULLiULLiULLi", "") BUILTIN(__builtin_cnttzdm, "ULLiULLiULLi", "") +// Double-double (un)pack +BUILTIN(__builtin_unpack_longdouble, "dLdIi", "") +BUILTIN(__builtin_pack_longdouble, "Lddd", "") + // Generate random number BUILTIN(__builtin_darn, "LLi", "") BUILTIN(__builtin_darn_raw, "LLi", "") diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fd5d7fb..1f2f84b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9802,6 +9802,8 @@ def err_ppc_builtin_only_on_arch : Error< "this builtin is only valid on POWER%0 or later CPUs">; def err_ppc_builtin_requires_vsx : Error< "this builtin requires VSX to be enabled">; +def err_ppc_builtin_requires_abi : Error< + "this builtin requires ABI -mabi=%0">; def err_ppc_invalid_use_mma_type : Error< "invalid use of PPC MMA type">; def err_ppc_invalid_test_data_class_type : Error< diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 84cebb0..172357b 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3382,6 +3382,18 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, case PPC::BI__builtin_tabortdci: return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) || SemaBuiltinConstantArgRange(TheCall, 2, 0, 31); + // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05', + // __builtin_(un)pack_longdouble are available only if long double uses IBM + // extended double representation. + case PPC::BI__builtin_unpack_longdouble: + if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 1)) + return true; + LLVM_FALLTHROUGH; + case PPC::BI__builtin_pack_longdouble: + if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble()) + return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_requires_abi) + << "ibmlongdouble"; + return false; case PPC::BI__builtin_altivec_dst: case PPC::BI__builtin_altivec_dstt: case PPC::BI__builtin_altivec_dstst: diff --git a/clang/test/CodeGen/builtins-ppc.c b/clang/test/CodeGen/builtins-ppc.c index 89c2df4..cbd5334 100644 --- a/clang/test/CodeGen/builtins-ppc.c +++ b/clang/test/CodeGen/builtins-ppc.c @@ -36,3 +36,13 @@ void test_builtin_ppc_flm() { // CHECK: call double @llvm.ppc.setflm(double %1) res = __builtin_setflm(res); } + +double test_builtin_unpack_ldbl(long double x) { + // CHECK: call double @llvm.ppc.unpack.longdouble(ppc_fp128 %0, i32 1) + return __builtin_unpack_longdouble(x, 1); +} + +long double test_builtin_pack_ldbl(double x, double y) { + // CHECK: call ppc_fp128 @llvm.ppc.pack.longdouble(double %0, double %1) + return __builtin_pack_longdouble(x, y); +} diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h index 80a2f5a..2ff4838 100644 --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -140,7 +140,8 @@ namespace Intrinsic { Subdivide2Argument, Subdivide4Argument, VecOfBitcastsToInt, - AMX + AMX, + PPCQuad, } Kind; union { diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td index e60bad8..8b158aa 100644 --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -50,6 +50,15 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_ppc_unpack_longdouble : GCCBuiltin<"__builtin_unpack_longdouble">, + Intrinsic<[llvm_double_ty], + [llvm_ppcf128_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_pack_longdouble : GCCBuiltin<"__builtin_pack_longdouble">, + Intrinsic<[llvm_ppcf128_ty], + [llvm_double_ty, llvm_double_ty], + [IntrNoMem]>; + // Generate a random number def int_ppc_darn : GCCBuiltin<"__builtin_darn">, Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>; diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 2049dc1..7eddffa 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -979,7 +979,8 @@ enum IIT_Info { IIT_BF16 = 48, IIT_STRUCT9 = 49, IIT_V256 = 50, - IIT_AMX = 51 + IIT_AMX = 51, + IIT_PPCF128 = 52 }; static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, @@ -1026,6 +1027,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, case IIT_F128: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0)); return; + case IIT_PPCF128: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::PPCQuad, 0)); + return; case IIT_I1: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1)); return; @@ -1250,6 +1254,7 @@ static Type *DecodeFixedType(ArrayRef &Infos, case IITDescriptor::Float: return Type::getFloatTy(Context); case IITDescriptor::Double: return Type::getDoubleTy(Context); case IITDescriptor::Quad: return Type::getFP128Ty(Context); + case IITDescriptor::PPCQuad: return Type::getPPC_FP128Ty(Context); case IITDescriptor::Integer: return IntegerType::get(Context, D.Integer_Width); @@ -1432,6 +1437,7 @@ static bool matchIntrinsicType( case IITDescriptor::Float: return !Ty->isFloatTy(); case IITDescriptor::Double: return !Ty->isDoubleTy(); case IITDescriptor::Quad: return !Ty->isFP128Ty(); + case IITDescriptor::PPCQuad: return !Ty->isPPC_FP128Ty(); case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width); case IITDescriptor::Vector: { VectorType *VT = dyn_cast(Ty); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index f2727b2..1ca59fe 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -601,6 +601,8 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, // We want to custom lower some of our intrinsics. setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::f64, Custom); + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::ppcf128, Custom); // To handle counter-based loop conditions. setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i1, Custom); @@ -10428,6 +10430,16 @@ SDValue PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, } return DAG.getMergeValues(RetOps, dl); } + + case Intrinsic::ppc_unpack_longdouble: { + auto *Idx = dyn_cast(Op.getOperand(2)); + assert(Idx && (Idx->getSExtValue() == 0 || Idx->getSExtValue() == 1) && + "Argument of long double unpack must be 0 or 1!"); + return DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::f64, Op.getOperand(1), + DAG.getConstant(!!(Idx->getSExtValue()), dl, + Idx->getValueType(0))); + } + case Intrinsic::ppc_compare_exp_lt: case Intrinsic::ppc_compare_exp_gt: case Intrinsic::ppc_compare_exp_eq: @@ -11109,6 +11121,15 @@ void PPCTargetLowering::ReplaceNodeResults(SDNode *N, Results.push_back(NewInt.getValue(1)); break; } + case ISD::INTRINSIC_WO_CHAIN: { + unsigned IntrinsicID = + cast(N->getOperand(0))->getZExtValue(); + + if (IntrinsicID == Intrinsic::ppc_pack_longdouble) + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::ppcf128, + N->getOperand(2), N->getOperand(1))); + break; + } case ISD::VAARG: { if (!Subtarget.isSVR4ABI() || Subtarget.isPPC64()) return; diff --git a/llvm/test/CodeGen/PowerPC/longdouble-pack.ll b/llvm/test/CodeGen/PowerPC/longdouble-pack.ll new file mode 100644 index 0000000..ec34dbb --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/longdouble-pack.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=powerpc64le-unknown-linux < %s | FileCheck %s +; RUN: llc -mtriple=powerpc64-ibm-aix-xcoff < %s | FileCheck %s + +define double @ldbl_1(ppc_fp128 %x) { +; CHECK-LABEL: ldbl_1: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: fmr 1, 2 +; CHECK-NEXT: blr +entry: + %0 = call double @llvm.ppc.unpack.longdouble(ppc_fp128 %x, i32 0) + ret double %0 +} + +define double @ldbl_2(ppc_fp128 %x) { +; CHECK-LABEL: ldbl_2: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: blr +entry: + %0 = call double @llvm.ppc.unpack.longdouble(ppc_fp128 %x, i32 1) + ret double %0 +} + +define ppc_fp128 @ldbl_pack(double %x, double %y) { +; CHECK-LABEL: ldbl_pack: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: blr +entry: + %0 = call ppc_fp128 @llvm.ppc.pack.longdouble(double %x, double %y) + ret ppc_fp128 %0 +} + +declare double @llvm.ppc.unpack.longdouble(ppc_fp128, i32) +declare ppc_fp128 @llvm.ppc.pack.longdouble(double, double) diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp index 3d1d258..437b5f0 100644 --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -249,7 +249,8 @@ enum IIT_Info { IIT_BF16 = 48, IIT_STRUCT9 = 49, IIT_V256 = 50, - IIT_AMX = 51 + IIT_AMX = 51, + IIT_PPCF128 = 52 }; static void EncodeFixedValueType(MVT::SimpleValueType VT, @@ -274,6 +275,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, case MVT::f32: return Sig.push_back(IIT_F32); case MVT::f64: return Sig.push_back(IIT_F64); case MVT::f128: return Sig.push_back(IIT_F128); + case MVT::ppcf128: return Sig.push_back(IIT_PPCF128); case MVT::token: return Sig.push_back(IIT_TOKEN); case MVT::Metadata: return Sig.push_back(IIT_METADATA); case MVT::x86mmx: return Sig.push_back(IIT_MMX);