diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc index 8d5049b15c..c911b4504c 100644 --- a/include/LLVMSPIRVExtensions.inc +++ b/include/LLVMSPIRVExtensions.inc @@ -63,4 +63,5 @@ EXT(SPV_INTEL_tensor_float32_rounding) EXT(SPV_EXT_relaxed_printf_string_address_space) EXT(SPV_INTEL_fpga_argument_interfaces) EXT(SPV_INTEL_fpga_latency_control) +EXT(SPV_INTEL_fp_max_error) EXT(SPV_INTEL_cache_controls) diff --git a/lib/SPIRV/SPIRVBuiltinHelper.cpp b/lib/SPIRV/SPIRVBuiltinHelper.cpp index edeb091433..a648cbac6d 100644 --- a/lib/SPIRV/SPIRVBuiltinHelper.cpp +++ b/lib/SPIRV/SPIRVBuiltinHelper.cpp @@ -102,6 +102,8 @@ Value *BuiltinCallMutator::doConversion() { CallInst *NewCall = Builder.Insert(addCallInst(CI->getModule(), FuncName, ReturnTy, Args, &Attrs, nullptr, Mangler.get())); + NewCall->copyMetadata(*CI); + NewCall->setAttributes(CI->getAttributes()); Value *Result = MutateRet ? MutateRet(Builder, NewCall) : NewCall; Result->takeName(CI); if (!CI->getType()->isVoidTy()) diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index 533c3a697e..12ecf70ac3 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -3893,7 +3893,48 @@ void SPIRVToLLVM::transDecorationsToMetadata(SPIRVValue *BV, Value *V) { SetDecorationsMetadata(I); } +namespace { + +static float convertSPIRVWordToFloat(SPIRVWord Spir) { + union { + float F; + SPIRVWord Spir; + } FPMaxError; + FPMaxError.Spir = Spir; + return FPMaxError.F; +} + +static bool transFPMaxErrorDecoration(SPIRVValue *BV, Value *V, + LLVMContext *Context) { + SPIRVWord ID; + if (Instruction *I = dyn_cast(V)) + if (BV->hasDecorate(DecorationFPMaxErrorDecorationINTEL, 0, &ID)) { + auto Literals = + BV->getDecorationLiterals(DecorationFPMaxErrorDecorationINTEL); + assert(Literals.size() == 1 && + "FP Max Error decoration shall have 1 operand"); + auto F = convertSPIRVWordToFloat(Literals[0]); + if (CallInst *CI = dyn_cast(I)) { + // Add attribute + auto A = llvm::Attribute::get(*Context, "fpbuiltin-max-error", + std::to_string(F)); + CI->addFnAttr(A); + } else { + // Add metadata + MDNode *N = + MDNode::get(*Context, MDString::get(*Context, std::to_string(F))); + I->setMetadata("fpbuiltin-max-error", N); + } + return true; + } + return false; +} +} // namespace + bool SPIRVToLLVM::transDecoration(SPIRVValue *BV, Value *V) { + if (transFPMaxErrorDecoration(BV, V, Context)) + return true; + if (!transAlign(BV, V)) return false; diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index f82ba7ba1c..47edb65f3b 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp @@ -106,6 +106,19 @@ using namespace llvm; using namespace SPIRV; using namespace OCLUtil; +namespace { + +static SPIRVWord convertFloatToSPIRVWord(float F) { + union { + float F; + SPIRVWord Spir; + } FPMaxError; + FPMaxError.F = F; + return FPMaxError.Spir; +} + +} // namespace + namespace SPIRV { static void foreachKernelArgMD( @@ -3481,6 +3494,26 @@ bool LLVMToSPIRVBase::isKnownIntrinsic(Intrinsic::ID Id) { } } +// Add decoration if needed +SPIRVInstruction *addFPBuiltinDecoration(SPIRVModule *BM, IntrinsicInst *II, + SPIRVInstruction *I) { + const bool AllowFPMaxError = + BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fp_max_error); + assert(II->getCalledFunction()->getName().startswith("llvm.fpbuiltin")); + // Add a new decoration for llvm.builtin intrinsics, if needed + if (AllowFPMaxError) + if (II->getAttributes().hasFnAttr("fpbuiltin-max-error")) { + double F = 0.0; + II->getAttributes() + .getFnAttr("fpbuiltin-max-error") + .getValueAsString() + .getAsDouble(F); + I->addDecorate(DecorationFPMaxErrorDecorationINTEL, + convertFloatToSPIRVWord(F)); + } + return I; +} + // Performs mapping of LLVM IR rounding mode to SPIR-V rounding mode // Value *V is metadata argument of // llvm.experimental.constrained.* intrinsics @@ -4424,8 +4457,9 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, } return Result; } - default: + if (auto *BVar = transFPBuiltinIntrinsicInst(II, BB)) + return BVar; if (BM->isUnknownIntrinsicAllowed(II)) return BM->addCallInst( transFunctionDecl(II->getCalledFunction()), @@ -4441,6 +4475,124 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II, return nullptr; } +LLVMToSPIRVBase::FPBuiltinType +LLVMToSPIRVBase::getFPBuiltinType(IntrinsicInst *II, StringRef &OpName) { + StringRef Name = II->getCalledFunction()->getName(); + if (!Name.startswith("llvm.fpbuiltin")) + return FPBuiltinType::UNKNOWN; + Name.consume_front("llvm.fpbuiltin."); + OpName = Name.split('.').first; + FPBuiltinType Type = + StringSwitch(OpName) + .Cases("fadd", "fsub", "fmul", "fdiv", "frem", + FPBuiltinType::REGULAR_MATH) + .Cases("sin", "cos", "tan", FPBuiltinType::EXT_1OPS) + .Cases("sinh", "cosh", "tanh", FPBuiltinType::EXT_1OPS) + .Cases("asin", "acos", "atan", FPBuiltinType::EXT_1OPS) + .Cases("asinh", "acosh", "atanh", FPBuiltinType::EXT_1OPS) + .Cases("exp", "exp2", "exp10", "expm1", FPBuiltinType::EXT_1OPS) + .Cases("log", "log2", "log10", "log1p", FPBuiltinType::EXT_1OPS) + .Cases("sqrt", "rsqrt", "erf", "erfc", FPBuiltinType::EXT_1OPS) + .Cases("atan2", "pow", "hypot", "ldexp", FPBuiltinType::EXT_2OPS) + .Case("sincos", FPBuiltinType::EXT_3OPS) + .Default(FPBuiltinType::UNKNOWN); + return Type; +} + +SPIRVValue *LLVMToSPIRVBase::transFPBuiltinIntrinsicInst(IntrinsicInst *II, + SPIRVBasicBlock *BB) { + StringRef OpName; + auto FPBuiltinTypeVal = getFPBuiltinType(II, OpName); + if (FPBuiltinTypeVal == FPBuiltinType::UNKNOWN) + return nullptr; + switch (FPBuiltinTypeVal) { + case FPBuiltinType::REGULAR_MATH: { + auto BinOp = StringSwitch(OpName) + .Case("fadd", OpFAdd) + .Case("fsub", OpFSub) + .Case("fmul", OpFMul) + .Case("fdiv", OpFDiv) + .Case("frem", OpFRem) + .Default(OpUndef); + auto *BI = BM->addBinaryInst(BinOp, transType(II->getType()), + transValue(II->getArgOperand(0), BB), + transValue(II->getArgOperand(1), BB), BB); + return addFPBuiltinDecoration(BM, II, BI); + } + case FPBuiltinType::EXT_1OPS: { + if (!checkTypeForSPIRVExtendedInstLowering(II, BM)) + break; + SPIRVType *STy = transType(II->getType()); + std::vector Ops(1, transValue(II->getArgOperand(0), BB)); + auto ExtOp = StringSwitch(OpName) + .Case("sin", OpenCLLIB::Sin) + .Case("cos", OpenCLLIB::Cos) + .Case("tan", OpenCLLIB::Tan) + .Case("sinh", OpenCLLIB::Sinh) + .Case("cosh", OpenCLLIB::Cosh) + .Case("tanh", OpenCLLIB::Tanh) + .Case("asin", OpenCLLIB::Asin) + .Case("acos", OpenCLLIB::Acos) + .Case("atan", OpenCLLIB::Atan) + .Case("asinh", OpenCLLIB::Asinh) + .Case("acosh", OpenCLLIB::Acosh) + .Case("atanh", OpenCLLIB::Atanh) + .Case("exp", OpenCLLIB::Exp) + .Case("exp2", OpenCLLIB::Exp2) + .Case("exp10", OpenCLLIB::Exp10) + .Case("expm1", OpenCLLIB::Expm1) + .Case("log", OpenCLLIB::Log) + .Case("log2", OpenCLLIB::Log2) + .Case("log10", OpenCLLIB::Log10) + .Case("log1p", OpenCLLIB::Log1p) + .Case("sqrt", OpenCLLIB::Sqrt) + .Case("rsqrt", OpenCLLIB::Rsqrt) + .Case("erf", OpenCLLIB::Erf) + .Case("erfc", OpenCLLIB::Erfc) + .Default(SPIRVWORD_MAX); + assert(ExtOp != SPIRVWORD_MAX); + auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, + Ops, BB); + return addFPBuiltinDecoration(BM, II, BI); + } + case FPBuiltinType::EXT_2OPS: { + if (!checkTypeForSPIRVExtendedInstLowering(II, BM)) + break; + SPIRVType *STy = transType(II->getType()); + std::vector Ops{transValue(II->getArgOperand(0), BB), + transValue(II->getArgOperand(1), BB)}; + auto ExtOp = StringSwitch(OpName) + .Case("atan2", OpenCLLIB::Atan2) + .Case("hypot", OpenCLLIB::Hypot) + .Case("pow", OpenCLLIB::Pow) + .Case("ldexp", OpenCLLIB::Ldexp) + .Default(SPIRVWORD_MAX); + assert(ExtOp != SPIRVWORD_MAX); + auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, + Ops, BB); + return addFPBuiltinDecoration(BM, II, BI); + } + case FPBuiltinType::EXT_3OPS: { + if (!checkTypeForSPIRVExtendedInstLowering(II, BM)) + break; + SPIRVType *STy = transType(II->getType()); + std::vector Ops{transValue(II->getArgOperand(0), BB), + transValue(II->getArgOperand(1), BB), + transValue(II->getArgOperand(2), BB)}; + auto ExtOp = StringSwitch(OpName) + .Case("sincos", OpenCLLIB::Sincos) + .Default(SPIRVWORD_MAX); + assert(ExtOp != SPIRVWORD_MAX); + auto *BI = BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, + Ops, BB); + return addFPBuiltinDecoration(BM, II, BI); + } + default: + return nullptr; + } + return nullptr; +} + SPIRVValue *LLVMToSPIRVBase::transFenceInst(FenceInst *FI, SPIRVBasicBlock *BB) { SPIRVWord MemorySemantics; diff --git a/lib/SPIRV/SPIRVWriter.h b/lib/SPIRV/SPIRVWriter.h index f71e36ce4d..2c11e15b91 100644 --- a/lib/SPIRV/SPIRVWriter.h +++ b/lib/SPIRV/SPIRVWriter.h @@ -108,6 +108,16 @@ class LLVMToSPIRVBase : protected BuiltinCallHelper { bool transBuiltinSet(); bool isKnownIntrinsic(Intrinsic::ID Id); SPIRVValue *transIntrinsicInst(IntrinsicInst *Intrinsic, SPIRVBasicBlock *BB); + enum class FPBuiltinType { + REGULAR_MATH, + EXT_1OPS, + EXT_2OPS, + EXT_3OPS, + UNKNOWN + }; + FPBuiltinType getFPBuiltinType(IntrinsicInst *II, StringRef &); + SPIRVValue *transFPBuiltinIntrinsicInst(IntrinsicInst *II, + SPIRVBasicBlock *BB); SPIRVValue *transFenceInst(FenceInst *FI, SPIRVBasicBlock *BB); SPIRVValue *transCallInst(CallInst *Call, SPIRVBasicBlock *BB); SPIRVValue *transDirectCallInst(CallInst *Call, SPIRVBasicBlock *BB); diff --git a/lib/SPIRV/libSPIRV/SPIRVDecorate.h b/lib/SPIRV/libSPIRV/SPIRVDecorate.h index 0060e6303e..c2fe345fde 100644 --- a/lib/SPIRV/libSPIRV/SPIRVDecorate.h +++ b/lib/SPIRV/libSPIRV/SPIRVDecorate.h @@ -201,6 +201,8 @@ class SPIRVDecorate : public SPIRVDecorateGeneric { case DecorationLatencyControlLabelINTEL: case DecorationLatencyControlConstraintINTEL: return ExtensionID::SPV_INTEL_fpga_latency_control; + case DecorationFPMaxErrorDecorationINTEL: + return ExtensionID::SPV_INTEL_fp_max_error; case internal::DecorationCacheControlLoadINTEL: case internal::DecorationCacheControlStoreINTEL: return ExtensionID::SPV_INTEL_cache_controls; diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h index df8853b7fe..7912f15db2 100644 --- a/lib/SPIRV/libSPIRV/SPIRVEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h @@ -497,6 +497,8 @@ template <> inline void SPIRVMap::init() { {CapabilityFPGALatencyControlINTEL}); ADD_VEC_INIT(DecorationLatencyControlConstraintINTEL, {CapabilityFPGALatencyControlINTEL}); + ADD_VEC_INIT(DecorationFPMaxErrorDecorationINTEL, + {CapabilityFPMaxErrorINTEL}); } template <> inline void SPIRVMap::init() { diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index d450a4381e..02f88123a8 100644 --- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -198,6 +198,7 @@ template <> inline void SPIRVMap::init() { add(DecorationStableKernelArgumentINTEL, "StableKernelArgumentINTEL"); add(DecorationLatencyControlLabelINTEL, "LatencyControlLabelINTEL"); add(DecorationLatencyControlConstraintINTEL, "LatencyControlConstraintINTEL"); + add(DecorationFPMaxErrorDecorationINTEL, "FPMaxErrorDecorationINTEL"); // From spirv_internal.hpp add(internal::DecorationCallableFunctionINTEL, "CallableFunctionINTEL"); @@ -623,6 +624,7 @@ template <> inline void SPIRVMap::init() { add(CapabilityMax, "Max"); add(CapabilityFPGAArgumentInterfacesINTEL, "FPGAArgumentInterfacesINTEL"); add(CapabilityFPGALatencyControlINTEL, "FPGALatencyControlINTEL"); + add(CapabilityFPMaxErrorINTEL, "FPMaxErrorINTEL"); // From spirv_internal.hpp add(internal::CapabilityFastCompositeINTEL, "FastCompositeINTEL"); add(internal::CapabilityOptNoneINTEL, "OptNoneINTEL"); diff --git a/spirv-headers-tag.conf b/spirv-headers-tag.conf index 9a532ba5d0..e28f5847a6 100644 --- a/spirv-headers-tag.conf +++ b/spirv-headers-tag.conf @@ -1 +1 @@ -9b527c0fb60124936d0906d44803bec51a0200fb +51b106461707f46d962554efe1bf56dee28958a3 diff --git a/test/extensions/INTEL/SPV_INTEL_fp_max_error/IntelFPMaxError.ll b/test/extensions/INTEL/SPV_INTEL_fp_max_error/IntelFPMaxError.ll new file mode 100644 index 0000000000..bc50f4fb40 --- /dev/null +++ b/test/extensions/INTEL/SPV_INTEL_fp_max_error/IntelFPMaxError.ll @@ -0,0 +1,250 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_fp_max_error --spirv-allow-unknown-intrinsics=llvm.fpbuiltin -o %t.spv +; RUN: llvm-spirv %t.spv -to-text -o %t.spt +; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV + +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + +; CHECK-SPIRV: Capability FPMaxErrorINTEL +; CHECK-SPIRV: Extension "SPV_INTEL_fp_max_error" +; CHECK-SPIRV: ExtInstImport [[#OCLEXTID:]] "OpenCL.std" + +; CHECK-SPIRV: Name [[#T1:]] "t1" +; CHECK-SPIRV: Name [[#T2:]] "t2" +; CHECK-SPIRV: Name [[#T3:]] "t3" +; CHECK-SPIRV: Name [[#T4:]] "t4" +; CHECK-SPIRV: Name [[#T5:]] "t5" +; CHECK-SPIRV: Name [[#T6:]] "t6" +; CHECK-SPIRV: Name [[#T7:]] "t7" +; CHECK-SPIRV: Name [[#T8:]] "t8" +; CHECK-SPIRV: Name [[#T9:]] "t9" +; CHECK-SPIRV: Name [[#T10:]] "t10" +; CHECK-SPIRV: Name [[#T11:]] "t11" +; CHECK-SPIRV: Name [[#T12:]] "t12" +; CHECK-SPIRV: Name [[#T13:]] "t13" +; CHECK-SPIRV: Name [[#T14:]] "t14" +; CHECK-SPIRV: Name [[#T15:]] "t15" +; CHECK-SPIRV: Name [[#T16:]] "t16" +; CHECK-SPIRV: Name [[#T17:]] "t17" +; CHECK-SPIRV: Name [[#T18:]] "t18" +; CHECK-SPIRV: Name [[#T19:]] "t19" +; CHECK-SPIRV: Name [[#T20:]] "t20" +; CHECK-SPIRV: Name [[#T21:]] "t21" +; CHECK-SPIRV: Name [[#T22:]] "t22" +; CHECK-SPIRV: Name [[#T23:]] "t23" +; CHECK-SPIRV: Name [[#T24:]] "t24" +; CHECK-SPIRV: Name [[#T25:]] "t25" +; CHECK-SPIRV: Name [[#T26:]] "t26" +; CHECK-SPIRV: Name [[#T27:]] "t27" +; CHECK-SPIRV: Name [[#T28:]] "t28" +; CHECK-SPIRV: Name [[#T29:]] "t29" +; CHECK-SPIRV: Name [[#T30:]] "t30" +; CHECK-SPIRV: Name [[#T31:]] "t31" +; CHECK-SPIRV: Name [[#T32:]] "t32" +; CHECK-SPIRV: Name [[#T33:]] "t33" +; CHECK-SPIRV: Name [[#T34:]] "t34" + +; CHECK-SPIRV: Decorate [[#T3]] FPMaxErrorDecorationINTEL 1056964608 +; CHECK-SPIRV: Decorate [[#T4]] FPMaxErrorDecorationINTEL 1065353216 +; CHECK-SPIRV: Decorate [[#T5]] FPMaxErrorDecorationINTEL 1065353216 +; CHECK-SPIRV: Decorate [[#T6]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T7]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T8]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T9]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T10]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T11]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T12]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T13]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T14]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T15]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T16]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T17]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T18]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T19]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T20]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T21]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T22]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T23]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T24]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T25]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T26]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T27]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T28]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T29]] FPMaxErrorDecorationINTEL 1075838976 +; CHECK-SPIRV: Decorate [[#T30]] FPMaxErrorDecorationINTEL 1082130432 +; CHECK-SPIRV: Decorate [[#T31]] FPMaxErrorDecorationINTEL 1082130432 +; CHECK-SPIRV: Decorate [[#T32]] FPMaxErrorDecorationINTEL 1082130432 +; CHECK-SPIRV: Decorate [[#T33]] FPMaxErrorDecorationINTEL 1082130432 +; CHECK-SPIRV: Decorate [[#T34]] FPMaxErrorDecorationINTEL 1166016512 + +; CHECK-SPIRV: 3 TypeFloat [[#FTYPE:]] 32 + +; CHECK-SPIRV: FAdd [[#FTYPE]] [[#T1]] +; CHECK-SPIRV: FSub [[#FTYPE]] [[#T2]] +; CHECK-SPIRV: FMul [[#FTYPE]] [[#T3]] +; CHECK-SPIRV: FDiv [[#FTYPE]] [[#T4]] +; CHECK-SPIRV: FRem [[#FTYPE]] [[#T5]] +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T6]] [[#OCLEXTID]] sin +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T7]] [[#OCLEXTID]] cos +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T8]] [[#OCLEXTID]] tan +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T9]] [[#OCLEXTID]] sinh +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T10]] [[#OCLEXTID]] cosh +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T11]] [[#OCLEXTID]] tanh +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T12]] [[#OCLEXTID]] asin +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T13]] [[#OCLEXTID]] acos +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T14]] [[#OCLEXTID]] atan +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T15]] [[#OCLEXTID]] asinh +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T16]] [[#OCLEXTID]] acosh +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T17]] [[#OCLEXTID]] atanh +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T18]] [[#OCLEXTID]] exp +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T19]] [[#OCLEXTID]] exp2 +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T20]] [[#OCLEXTID]] exp10 +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T21]] [[#OCLEXTID]] expm1 +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T22]] [[#OCLEXTID]] log +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T23]] [[#OCLEXTID]] log2 +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T24]] [[#OCLEXTID]] log10 +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T25]] [[#OCLEXTID]] log1p +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T26]] [[#OCLEXTID]] sqrt +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T27]] [[#OCLEXTID]] rsqrt +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T28]] [[#OCLEXTID]] erf +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T29]] [[#OCLEXTID]] erfc +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T30]] [[#OCLEXTID]] atan2 +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T31]] [[#OCLEXTID]] ldexp +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T32]] [[#OCLEXTID]] pow +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T33]] [[#OCLEXTID]] hypot +; CHECK-SPIRV: ExtInst [[#FTYPE]] [[#T34]] [[#OCLEXTID]] hypot + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +target triple = "spir64-unknown-unknown" + +define void @test_fp_max_error_decoration(float %f1, float %f2, float %f3) { +entry: +; CHECK-LLVM-NOT: fadd float %f1, %f2, !fpbuiltin-max-error +; CHECK-LLVM-NOT: fsub float %f1, %f2, !fpbuiltin-max-error +; CHECK-LLVM: fmul float %f1, %f2, !fpbuiltin-max-error ![[#ME1:]] +; CHECK-LLVM: fdiv float %f1, %f2, !fpbuiltin-max-error ![[#ME2:]] +; CHECK-LLVM: frem float %f1, %f2, !fpbuiltin-max-error ![[#ME2]] + %t1 = call float @llvm.fpbuiltin.fadd.f32(float %f1, float %f2) + %t2 = call float @llvm.fpbuiltin.fsub.f32(float %f1, float %f2) + %t3 = call float @llvm.fpbuiltin.fmul.f32(float %f1, float %f2) #0 + %t4 = call float @llvm.fpbuiltin.fdiv.f32(float %f1, float %f2) #1 + %t5 = call float @llvm.fpbuiltin.frem.f32(float %f1, float %f2) #1 + +; CHECK-LLVM: call spir_func float @_Z3sinf(float %f1) #[[#AT3:]] +; CHECK-LLVM: call spir_func float @_Z3cosf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z3tanf(float %f1) #[[#AT3]] + %t6 = call float @llvm.fpbuiltin.sin.f32(float %f1) #2 + %t7 = call float @llvm.fpbuiltin.cos.f32(float %f1) #2 + %t8 = call float @llvm.fpbuiltin.tan.f32(float %f1) #2 + +; CHECK-LLVM: call spir_func float @_Z4sinhf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z4coshf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z4tanhf(float %f1) #[[#AT3]] + %t9 = call float @llvm.fpbuiltin.sinh.f32(float %f1) #2 + %t10 = call float @llvm.fpbuiltin.cosh.f32(float %f1) #2 + %t11 = call float @llvm.fpbuiltin.tanh.f32(float %f1) #2 + +; CHECK-LLVM: call spir_func float @_Z4asinf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z4acosf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z4atanf(float %f1) #[[#AT3]] + %t12 = call float @llvm.fpbuiltin.asin.f32(float %f1) #2 + %t13 = call float @llvm.fpbuiltin.acos.f32(float %f1) #2 + %t14 = call float @llvm.fpbuiltin.atan.f32(float %f1) #2 + +; CHECK-LLVM:15 = call spir_func float @_Z5asinhf(float %f1) #[[#AT3]] +; CHECK-LLVM:16 = call spir_func float @_Z5acoshf(float %f1) #[[#AT3]] +; CHECK-LLVM:17 = call spir_func float @_Z5atanhf(float %f1) #[[#AT3]] + %t15 = call float @llvm.fpbuiltin.asinh.f32(float %f1) #2 + %t16 = call float @llvm.fpbuiltin.acosh.f32(float %f1) #2 + %t17 = call float @llvm.fpbuiltin.atanh.f32(float %f1) #2 + +; CHECK-LLVM:18 = call spir_func float @_Z3expf(float %f1) #[[#AT3]] +; CHECK-LLVM:19 = call spir_func float @_Z4exp2f(float %f1) #[[#AT3]] +; CHECK-LLVM:20 = call spir_func float @_Z5exp10f(float %f1) #[[#AT3]] +; CHECK-LLVM:21 = call spir_func float @_Z5expm1f(float %f1) #[[#AT3]] + %t18 = call float @llvm.fpbuiltin.exp.f32(float %f1) #2 + %t19 = call float @llvm.fpbuiltin.exp2.f32(float %f1) #2 + %t20 = call float @llvm.fpbuiltin.exp10.f32(float %f1) #2 + %t21 = call float @llvm.fpbuiltin.expm1.f32(float %f1) #2 + +; CHECK-LLVM: call spir_func float @_Z3logf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z4log2f(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z5log10f(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z5log1pf(float %f1) #[[#AT3]] + %t22 = call float @llvm.fpbuiltin.log.f32(float %f1) #2 + %t23 = call float @llvm.fpbuiltin.log2.f32(float %f1) #2 + %t24 = call float @llvm.fpbuiltin.log10.f32(float %f1) #2 + %t25 = call float @llvm.fpbuiltin.log1p.f32(float %f1) #2 + +; CHECK-LLVM: call spir_func float @_Z4sqrtf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z5rsqrtf(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z3erff(float %f1) #[[#AT3]] +; CHECK-LLVM: call spir_func float @_Z4erfcf(float %f1) #[[#AT3]] + %t26 = call float @llvm.fpbuiltin.sqrt.f32(float %f1) #2 + %t27 = call float @llvm.fpbuiltin.rsqrt.f32(float %f1) #2 + %t28 = call float @llvm.fpbuiltin.erf.f32(float %f1) #2 + %t29 = call float @llvm.fpbuiltin.erfc.f32(float %f1) #2 + +; CHECK-LLVM: call spir_func float @_Z5atan2ff(float %f1, float %f2) #[[#AT4:]] +; CHECK-LLVM: call spir_func float @_Z5ldexpff(float %f1, float %f2) #[[#AT4]] +; CHECK-LLVM: call spir_func float @_Z3powff(float %f1, float %f2) #[[#AT4]] +; CHECK-LLVM: call spir_func float @_Z5hypotff(float %f1, float %f2) #[[#AT4]] + %t30 = call float @llvm.fpbuiltin.atan2.f32(float %f1, float %f2) #3 + %t31 = call float @llvm.fpbuiltin.ldexp.f32(float %f1, float %f2) #3 + %t32 = call float @llvm.fpbuiltin.pow.f32(float %f1, float %f2) #3 + %t33 = call float @llvm.fpbuiltin.hypot.f32(float %f1, float %f2) #3 + + ; CHECK-LLVM: call spir_func float @_Z5hypotff(float %f1, float %f2) #[[#AT5:]] + %t34 = call float @llvm.fpbuiltin.hypot.f32(float %f1, float %f2) #4 + + ret void +} + +declare float @llvm.fpbuiltin.fadd.f32(float, float) +declare float @llvm.fpbuiltin.fsub.f32(float, float) +declare float @llvm.fpbuiltin.fmul.f32(float, float) +declare float @llvm.fpbuiltin.fdiv.f32(float, float) +declare float @llvm.fpbuiltin.frem.f32(float, float) + +declare float @llvm.fpbuiltin.sin.f32(float) +declare float @llvm.fpbuiltin.cos.f32(float) +declare float @llvm.fpbuiltin.tan.f32(float) +declare float @llvm.fpbuiltin.sinh.f32(float) +declare float @llvm.fpbuiltin.cosh.f32(float) +declare float @llvm.fpbuiltin.tanh.f32(float) +declare float @llvm.fpbuiltin.asin.f32(float) +declare float @llvm.fpbuiltin.acos.f32(float) +declare float @llvm.fpbuiltin.atan.f32(float) +declare float @llvm.fpbuiltin.asinh.f32(float) +declare float @llvm.fpbuiltin.acosh.f32(float) +declare float @llvm.fpbuiltin.atanh.f32(float) +declare float @llvm.fpbuiltin.exp.f32(float) +declare float @llvm.fpbuiltin.exp2.f32(float) +declare float @llvm.fpbuiltin.exp10.f32(float) +declare float @llvm.fpbuiltin.expm1.f32(float) +declare float @llvm.fpbuiltin.log.f32(float) +declare float @llvm.fpbuiltin.log2.f32(float) +declare float @llvm.fpbuiltin.log10.f32(float) +declare float @llvm.fpbuiltin.log1p.f32(float) +declare float @llvm.fpbuiltin.sqrt.f32(float) +declare float @llvm.fpbuiltin.rsqrt.f32(float) +declare float @llvm.fpbuiltin.erf.f32(float) +declare float @llvm.fpbuiltin.erfc.f32(float) + +declare float @llvm.fpbuiltin.atan2.f32(float, float) +declare float @llvm.fpbuiltin.hypot.f32(float, float) +declare float @llvm.fpbuiltin.pow.f32(float, float) +declare float @llvm.fpbuiltin.ldexp.f32(float, float) + +; CHECK-LLVM: attributes #[[#AT3]] = {{{.*}} "fpbuiltin-max-error"="2.5{{0+}}" {{.*}}} +; CHECK-LLVM: attributes #[[#AT4]] = {{{.*}} "fpbuiltin-max-error"="4.0{{0+}}" {{.*}}} +; CHECK-LLVM: attributes #[[#AT5]] = {{{.*}} "fpbuiltin-max-error"="4096.0{{0+}}" {{.*}}} +; CHECK-LLVM: ![[#ME1]] = !{!"0.500000"} +; CHECK-LLVM: ![[#ME2]] = !{!"1.000000"} + +attributes #0 = { "fpbuiltin-max-error"="0.5" } +attributes #1 = { "fpbuiltin-max-error"="1.0" } +attributes #2 = { "fpbuiltin-max-error"="2.5" } +attributes #3 = { "fpbuiltin-max-error"="4.0" } +attributes #4 = { "fpbuiltin-max-error"="4096.0" }