Index: include/llvm/IR/Intrinsics.h =================================================================== --- include/llvm/IR/Intrinsics.h +++ include/llvm/IR/Intrinsics.h @@ -97,7 +97,7 @@ /// 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 Index: include/llvm/IR/IntrinsicsPowerPC.td =================================================================== --- include/llvm/IR/IntrinsicsPowerPC.td +++ include/llvm/IR/IntrinsicsPowerPC.td @@ -61,6 +61,26 @@ 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]>; + } Index: lib/IR/Function.cpp =================================================================== --- lib/IR/Function.cpp +++ lib/IR/Function.cpp @@ -673,7 +673,8 @@ IIT_V1024 = 37, IIT_STRUCT6 = 38, IIT_STRUCT7 = 39, - IIT_STRUCT8 = 40 + IIT_STRUCT8 = 40, + IIT_F128 = 41 }; static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, @@ -708,6 +709,9 @@ 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; @@ -892,6 +896,7 @@ 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); @@ -1034,6 +1039,7 @@ 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(Ty); Index: lib/Target/PowerPC/PPCInstrVSX.td =================================================================== --- lib/Target/PowerPC/PPCInstrVSX.td +++ lib/Target/PowerPC/PPCInstrVSX.td @@ -2437,30 +2437,54 @@ 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 : Pat<(int_ppc_fmaf128_round_to_odd f128:$vA,f128:$vB,f128:$vTi), + (XSMADDQPO $vA,$vB,$vTi)>; + def XSMSUBQP : X_VT5_VA5_VB5_FMA <63, 420, "xsmsubqp" , [(set f128:$vT, (fma f128:$vA, f128:$vB, Index: test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/builtins-ppc-p9-f128.ll @@ -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) + Index: utils/TableGen/IntrinsicEmitter.cpp =================================================================== --- utils/TableGen/IntrinsicEmitter.cpp +++ utils/TableGen/IntrinsicEmitter.cpp @@ -217,7 +217,8 @@ IIT_V1024 = 37, IIT_STRUCT6 = 38, IIT_STRUCT7 = 39, - IIT_STRUCT8 = 40 + IIT_STRUCT8 = 40, + IIT_F128 = 41 }; static void EncodeFixedValueType(MVT::SimpleValueType VT, @@ -240,6 +241,7 @@ 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);