[clang] 741aeda - [PowerPC] Implement longdouble pack/unpack builtins
Qiu Chaofan via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 3 03:05:00 PDT 2021
Author: Qiu Chaofan
Date: 2021-11-03T17:57:25+08:00
New Revision: 741aeda97d6327edd9905b21a5308fcee21bbefd
URL: https://github.com/llvm/llvm-project/commit/741aeda97d6327edd9905b21a5308fcee21bbefd
DIFF: https://github.com/llvm/llvm-project/commit/741aeda97d6327edd9905b21a5308fcee21bbefd.diff
LOG: [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
Added:
llvm/test/CodeGen/PowerPC/longdouble-pack.ll
Modified:
clang/include/clang/Basic/BuiltinsPPC.def
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaChecking.cpp
clang/test/CodeGen/builtins-ppc.c
llvm/include/llvm/IR/Intrinsics.h
llvm/include/llvm/IR/IntrinsicsPowerPC.td
llvm/lib/IR/Function.cpp
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/utils/TableGen/IntrinsicEmitter.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def
index f82d455506860..cd6b2df10e521 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 fd5d7fb8168c6..1f2f84bdee4b8 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 84cebb03b5f02..172357be9d862 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 89c2df45a9f56..cbd53346d4b0f 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 80a2f5a8cd3e4..2ff48380ac282 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 e60bad8fd9f0c..8b158aa99de0e 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 2049dc16a3c15..7eddffab13b9d 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<unsigned char> Infos,
@@ -1026,6 +1027,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> 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<Intrinsic::IITDescriptor> &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<VectorType>(Ty);
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index f2727b2381098..1ca59feef42e8 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<ConstantSDNode>(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<ConstantSDNode>(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 0000000000000..ec34dbbd92945
--- /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 3d1d258e342e9..437b5f002027c 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);
More information about the cfe-commits
mailing list