/// intrinsic. This is returned by getIntrinsicInfoTableEntries.
struct IITDescriptor {
enum IITDescriptorKind {
- Void, VarArg, MMX, Token, Metadata, Half, Float, Double,
+ Void, VarArg, MMX, Token, Metadata, Half, Float, Double, Quad,
Integer, Vector, Pointer, Struct,
Argument, ExtendArgument, TruncArgument, HalfVecArgument,
SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt
def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">,
Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
[IntrNoMem]>;
+
+ def int_ppc_sqrtf128_round_to_odd
+ : GCCBuiltin<"__builtin_sqrtf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_addf128_round_to_odd
+ : GCCBuiltin<"__builtin_addf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_subf128_round_to_odd
+ : GCCBuiltin<"__builtin_subf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_mulf128_round_to_odd
+ : GCCBuiltin<"__builtin_mulf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_divf128_round_to_odd
+ : GCCBuiltin<"__builtin_divf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+ def int_ppc_fmaf128_round_to_odd
+ : GCCBuiltin<"__builtin_fmaf128_round_to_odd">,
+ Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>;
+
}
IIT_V1024 = 37,
IIT_STRUCT6 = 38,
IIT_STRUCT7 = 39,
- IIT_STRUCT8 = 40
+ IIT_STRUCT8 = 40,
+ IIT_F128 = 41
};
static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
case IIT_F64:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0));
return;
+ case IIT_F128:
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0));
+ return;
case IIT_I1:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1));
return;
case IITDescriptor::Half: return Type::getHalfTy(Context);
case IITDescriptor::Float: return Type::getFloatTy(Context);
case IITDescriptor::Double: return Type::getDoubleTy(Context);
+ case IITDescriptor::Quad: return Type::getFP128Ty(Context);
case IITDescriptor::Integer:
return IntegerType::get(Context, D.Integer_Width);
case IITDescriptor::Half: return !Ty->isHalfTy();
case IITDescriptor::Float: return !Ty->isFloatTy();
case IITDescriptor::Double: return !Ty->isDoubleTy();
+ case IITDescriptor::Quad: return !Ty->isFP128Ty();
case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width);
case IITDescriptor::Vector: {
VectorType *VT = dyn_cast<VectorType>(Ty);
let isCommutable = 1 in {
def XSADDQP : X_VT5_VA5_VB5 <63, 4, "xsaddqp",
[(set f128:$vT, (fadd f128:$vA, f128:$vB))]>;
- def XSADDQPO : X_VT5_VA5_VB5_Ro<63, 4, "xsaddqpo", []>;
+ def XSADDQPO : X_VT5_VA5_VB5_Ro<63, 4, "xsaddqpo",
+ [(set f128:$vT,
+ (int_ppc_addf128_round_to_odd
+ f128:$vA, f128:$vB))]>;
def XSMULQP : X_VT5_VA5_VB5 <63, 36, "xsmulqp",
[(set f128:$vT, (fmul f128:$vA, f128:$vB))]>;
- def XSMULQPO : X_VT5_VA5_VB5_Ro<63, 36, "xsmulqpo", []>;
+ def XSMULQPO : X_VT5_VA5_VB5_Ro<63, 36, "xsmulqpo",
+ [(set f128:$vT,
+ (int_ppc_mulf128_round_to_odd
+ f128:$vA, f128:$vB))]>;
}
def XSSUBQP : X_VT5_VA5_VB5 <63, 516, "xssubqp" ,
[(set f128:$vT, (fsub f128:$vA, f128:$vB))]>;
- def XSSUBQPO : X_VT5_VA5_VB5_Ro<63, 516, "xssubqpo", []>;
+ def XSSUBQPO : X_VT5_VA5_VB5_Ro<63, 516, "xssubqpo",
+ [(set f128:$vT,
+ (int_ppc_subf128_round_to_odd
+ f128:$vA, f128:$vB))]>;
def XSDIVQP : X_VT5_VA5_VB5 <63, 548, "xsdivqp",
[(set f128:$vT, (fdiv f128:$vA, f128:$vB))]>;
- def XSDIVQPO : X_VT5_VA5_VB5_Ro<63, 548, "xsdivqpo", []>;
+ def XSDIVQPO : X_VT5_VA5_VB5_Ro<63, 548, "xsdivqpo",
+ [(set f128:$vT,
+ (int_ppc_divf128_round_to_odd
+ f128:$vA, f128:$vB))]>;
// Square-Root
def XSSQRTQP : X_VT5_XO5_VB5 <63, 27, 804, "xssqrtqp",
[(set f128:$vT, (fsqrt f128:$vB))]>;
- def XSSQRTQPO : X_VT5_XO5_VB5_Ro<63, 27, 804, "xssqrtqpo", []>;
+ def XSSQRTQPO : X_VT5_XO5_VB5_Ro<63, 27, 804, "xssqrtqpo",
+ [(set f128:$vT,
+ (int_ppc_sqrtf128_round_to_odd f128:$vB))]>;
// (Negative) Multiply-{Add/Subtract}
def XSMADDQP : X_VT5_VA5_VB5_FMA <63, 388, "xsmaddqp",
[(set f128:$vT,
(fma f128:$vA, f128:$vB,
f128:$vTi))]>;
- def XSMADDQPO : X_VT5_VA5_VB5_FMA_Ro<63, 388, "xsmaddqpo" , []>;
+
+ def XSMADDQPO : X_VT5_VA5_VB5_FMA_Ro<63, 388, "xsmaddqpo",
+ [(set f128:$vT,
+ (int_ppc_fmaf128_round_to_odd
+ f128:$vA,f128:$vB,f128:$vTi))]>;
+
def XSMSUBQP : X_VT5_VA5_VB5_FMA <63, 420, "xsmsubqp" ,
[(set f128:$vT,
(fma f128:$vA, f128:$vB,
--- /dev/null
+; RUN: llc -verify-machineinstrs -mcpu=pwr9 -enable-ppc-quad-precision \
+; RUN: -mtriple=powerpc64le-unknown-unknown < %s | FileCheck %s
+
+@A = common global fp128 0xL00000000000000000000000000000000, align 16
+@B = common global fp128 0xL00000000000000000000000000000000, align 16
+@C = common global fp128 0xL00000000000000000000000000000000, align 16
+
+define fp128 @testSqrtOdd() {
+entry:
+ %0 = load fp128, fp128* @A, align 16
+ %1 = call fp128 @llvm.ppc.sqrtf128.round.to.odd(fp128 %0)
+ ret fp128 %1
+; CHECK-LABEL: testSqrtOdd
+; CHECK: xssqrtqpo
+}
+
+declare fp128 @llvm.ppc.sqrtf128.round.to.odd(fp128)
+
+define fp128 @testFMAOdd() {
+entry:
+ %0 = load fp128, fp128* @A, align 16
+ %1 = load fp128, fp128* @B, align 16
+ %2 = load fp128, fp128* @C, align 16
+ %3 = call fp128 @llvm.ppc.fmaf128.round.to.odd(fp128 %0, fp128 %1, fp128 %2)
+ ret fp128 %3
+; CHECK-LABEL: testFMAOdd
+; CHECK: xsmaddqpo
+}
+
+declare fp128 @llvm.ppc.fmaf128.round.to.odd(fp128, fp128, fp128)
+
+define fp128 @testAddOdd() {
+entry:
+ %0 = load fp128, fp128* @A, align 16
+ %1 = load fp128, fp128* @B, align 16
+ %2 = call fp128 @llvm.ppc.addf128.round.to.odd(fp128 %0, fp128 %1)
+ ret fp128 %2
+; CHECK-LABEL: testAddOdd
+; CHECK: xsaddqpo
+}
+
+declare fp128 @llvm.ppc.addf128.round.to.odd(fp128, fp128)
+
+define fp128 @testSubOdd() {
+entry:
+ %0 = load fp128, fp128* @A, align 16
+ %1 = load fp128, fp128* @B, align 16
+ %2 = call fp128 @llvm.ppc.subf128.round.to.odd(fp128 %0, fp128 %1)
+ ret fp128 %2
+; CHECK-LABEL: testSubOdd
+; CHECK: xssubqpo
+}
+
+; Function Attrs: nounwind readnone
+declare fp128 @llvm.ppc.subf128.round.to.odd(fp128, fp128)
+
+; Function Attrs: noinline nounwind optnone
+define fp128 @testMulOdd() {
+entry:
+ %0 = load fp128, fp128* @A, align 16
+ %1 = load fp128, fp128* @B, align 16
+ %2 = call fp128 @llvm.ppc.mulf128.round.to.odd(fp128 %0, fp128 %1)
+ ret fp128 %2
+; CHECK-LABEL: testMulOdd
+; CHECK: xsmulqpo
+}
+
+; Function Attrs: nounwind readnone
+declare fp128 @llvm.ppc.mulf128.round.to.odd(fp128, fp128)
+
+define fp128 @testDivOdd() {
+entry:
+ %0 = load fp128, fp128* @A, align 16
+ %1 = load fp128, fp128* @B, align 16
+ %2 = call fp128 @llvm.ppc.divf128.round.to.odd(fp128 %0, fp128 %1)
+ ret fp128 %2
+; CHECK-LABEL: testDivOdd
+; CHECK: xsdivqpo
+}
+
+declare fp128 @llvm.ppc.divf128.round.to.odd(fp128, fp128)
+
IIT_V1024 = 37,
IIT_STRUCT6 = 38,
IIT_STRUCT7 = 39,
- IIT_STRUCT8 = 40
+ IIT_STRUCT8 = 40,
+ IIT_F128 = 41
};
static void EncodeFixedValueType(MVT::SimpleValueType VT,
case MVT::f16: return Sig.push_back(IIT_F16);
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::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);