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", "")
"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<
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:
// 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);
+}
Subdivide2Argument,
Subdivide4Argument,
VecOfBitcastsToInt,
- AMX
+ AMX,
+ PPCQuad,
} Kind;
union {
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]>;
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,
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;
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);
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);
// 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);
}
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:
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;
--- /dev/null
+; 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)
IIT_BF16 = 48,
IIT_STRUCT9 = 49,
IIT_V256 = 50,
- IIT_AMX = 51
+ IIT_AMX = 51,
+ IIT_PPCF128 = 52
};
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);