forked from OSchip/llvm-project
[Power9] Add __float128 builtins for Round To Odd
GCC has builtins for these round to odd instructions: __float128 __builtin_sqrtf128_round_to_odd (__float128) __float128 __builtin_{add,sub,mul,div}f128_round_to_odd (__float128, __float128) __float128 __builtin_fmaf128_round_to_odd (__float128, __float128, __float128) Differential Revision: https://reviews.llvm.org/D47550 llvm-svn: 336578
This commit is contained in:
parent
fa762cc19b
commit
83a5fe146e
|
@ -97,7 +97,7 @@ namespace Intrinsic {
|
||||||
/// intrinsic. This is returned by getIntrinsicInfoTableEntries.
|
/// intrinsic. This is returned by getIntrinsicInfoTableEntries.
|
||||||
struct IITDescriptor {
|
struct IITDescriptor {
|
||||||
enum IITDescriptorKind {
|
enum IITDescriptorKind {
|
||||||
Void, VarArg, MMX, Token, Metadata, Half, Float, Double,
|
Void, VarArg, MMX, Token, Metadata, Half, Float, Double, Quad,
|
||||||
Integer, Vector, Pointer, Struct,
|
Integer, Vector, Pointer, Struct,
|
||||||
Argument, ExtendArgument, TruncArgument, HalfVecArgument,
|
Argument, ExtendArgument, TruncArgument, HalfVecArgument,
|
||||||
SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt
|
SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt
|
||||||
|
|
|
@ -61,6 +61,26 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
|
||||||
def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">,
|
def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">,
|
||||||
Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
|
Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
|
||||||
[IntrNoMem]>;
|
[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]>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -673,7 +673,8 @@ enum IIT_Info {
|
||||||
IIT_V1024 = 37,
|
IIT_V1024 = 37,
|
||||||
IIT_STRUCT6 = 38,
|
IIT_STRUCT6 = 38,
|
||||||
IIT_STRUCT7 = 39,
|
IIT_STRUCT7 = 39,
|
||||||
IIT_STRUCT8 = 40
|
IIT_STRUCT8 = 40,
|
||||||
|
IIT_F128 = 41
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
|
static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
|
||||||
|
@ -708,6 +709,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
|
||||||
case IIT_F64:
|
case IIT_F64:
|
||||||
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0));
|
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0));
|
||||||
return;
|
return;
|
||||||
|
case IIT_F128:
|
||||||
|
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0));
|
||||||
|
return;
|
||||||
case IIT_I1:
|
case IIT_I1:
|
||||||
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1));
|
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1));
|
||||||
return;
|
return;
|
||||||
|
@ -892,6 +896,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
|
||||||
case IITDescriptor::Half: return Type::getHalfTy(Context);
|
case IITDescriptor::Half: return Type::getHalfTy(Context);
|
||||||
case IITDescriptor::Float: return Type::getFloatTy(Context);
|
case IITDescriptor::Float: return Type::getFloatTy(Context);
|
||||||
case IITDescriptor::Double: return Type::getDoubleTy(Context);
|
case IITDescriptor::Double: return Type::getDoubleTy(Context);
|
||||||
|
case IITDescriptor::Quad: return Type::getFP128Ty(Context);
|
||||||
|
|
||||||
case IITDescriptor::Integer:
|
case IITDescriptor::Integer:
|
||||||
return IntegerType::get(Context, D.Integer_Width);
|
return IntegerType::get(Context, D.Integer_Width);
|
||||||
|
@ -1034,6 +1039,7 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
||||||
case IITDescriptor::Half: return !Ty->isHalfTy();
|
case IITDescriptor::Half: return !Ty->isHalfTy();
|
||||||
case IITDescriptor::Float: return !Ty->isFloatTy();
|
case IITDescriptor::Float: return !Ty->isFloatTy();
|
||||||
case IITDescriptor::Double: return !Ty->isDoubleTy();
|
case IITDescriptor::Double: return !Ty->isDoubleTy();
|
||||||
|
case IITDescriptor::Quad: return !Ty->isFP128Ty();
|
||||||
case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width);
|
case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width);
|
||||||
case IITDescriptor::Vector: {
|
case IITDescriptor::Vector: {
|
||||||
VectorType *VT = dyn_cast<VectorType>(Ty);
|
VectorType *VT = dyn_cast<VectorType>(Ty);
|
||||||
|
|
|
@ -2451,30 +2451,49 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in {
|
||||||
let isCommutable = 1 in {
|
let isCommutable = 1 in {
|
||||||
def XSADDQP : X_VT5_VA5_VB5 <63, 4, "xsaddqp",
|
def XSADDQP : X_VT5_VA5_VB5 <63, 4, "xsaddqp",
|
||||||
[(set f128:$vT, (fadd f128:$vA, f128:$vB))]>;
|
[(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",
|
def XSMULQP : X_VT5_VA5_VB5 <63, 36, "xsmulqp",
|
||||||
[(set f128:$vT, (fmul f128:$vA, f128:$vB))]>;
|
[(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" ,
|
def XSSUBQP : X_VT5_VA5_VB5 <63, 516, "xssubqp" ,
|
||||||
[(set f128:$vT, (fsub f128:$vA, f128:$vB))]>;
|
[(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",
|
def XSDIVQP : X_VT5_VA5_VB5 <63, 548, "xsdivqp",
|
||||||
[(set f128:$vT, (fdiv f128:$vA, f128:$vB))]>;
|
[(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
|
// Square-Root
|
||||||
def XSSQRTQP : X_VT5_XO5_VB5 <63, 27, 804, "xssqrtqp",
|
def XSSQRTQP : X_VT5_XO5_VB5 <63, 27, 804, "xssqrtqp",
|
||||||
[(set f128:$vT, (fsqrt f128:$vB))]>;
|
[(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}
|
// (Negative) Multiply-{Add/Subtract}
|
||||||
def XSMADDQP : X_VT5_VA5_VB5_FMA <63, 388, "xsmaddqp",
|
def XSMADDQP : X_VT5_VA5_VB5_FMA <63, 388, "xsmaddqp",
|
||||||
[(set f128:$vT,
|
[(set f128:$vT,
|
||||||
(fma f128:$vA, f128:$vB,
|
(fma f128:$vA, f128:$vB,
|
||||||
f128:$vTi))]>;
|
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" ,
|
def XSMSUBQP : X_VT5_VA5_VB5_FMA <63, 420, "xsmsubqp" ,
|
||||||
[(set f128:$vT,
|
[(set f128:$vT,
|
||||||
(fma f128:$vA, f128:$vB,
|
(fma f128:$vA, f128:$vB,
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
; 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)
|
||||||
|
|
|
@ -219,7 +219,8 @@ enum IIT_Info {
|
||||||
IIT_V1024 = 37,
|
IIT_V1024 = 37,
|
||||||
IIT_STRUCT6 = 38,
|
IIT_STRUCT6 = 38,
|
||||||
IIT_STRUCT7 = 39,
|
IIT_STRUCT7 = 39,
|
||||||
IIT_STRUCT8 = 40
|
IIT_STRUCT8 = 40,
|
||||||
|
IIT_F128 = 41
|
||||||
};
|
};
|
||||||
|
|
||||||
static void EncodeFixedValueType(MVT::SimpleValueType VT,
|
static void EncodeFixedValueType(MVT::SimpleValueType VT,
|
||||||
|
@ -242,6 +243,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
|
||||||
case MVT::f16: return Sig.push_back(IIT_F16);
|
case MVT::f16: return Sig.push_back(IIT_F16);
|
||||||
case MVT::f32: return Sig.push_back(IIT_F32);
|
case MVT::f32: return Sig.push_back(IIT_F32);
|
||||||
case MVT::f64: return Sig.push_back(IIT_F64);
|
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::token: return Sig.push_back(IIT_TOKEN);
|
||||||
case MVT::Metadata: return Sig.push_back(IIT_METADATA);
|
case MVT::Metadata: return Sig.push_back(IIT_METADATA);
|
||||||
case MVT::x86mmx: return Sig.push_back(IIT_MMX);
|
case MVT::x86mmx: return Sig.push_back(IIT_MMX);
|
||||||
|
|
Loading…
Reference in New Issue