Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/LLVMSPIRVExtensions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ EXT(SPV_INTEL_optimization_hints)
EXT(SPV_INTEL_float_controls2)
EXT(SPV_INTEL_vector_compute)
EXT(SPV_INTEL_usm_storage_classes)
EXT(SPV_INTEL_arbitrary_precision_fixed_point)
31 changes: 31 additions & 0 deletions lib/SPIRV/OCLUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ const static char Clamp[] = "clamp";
const static char ConvertPrefix[] = "convert_";
const static char Dot[] = "dot";
const static char EnqueueKernel[] = "enqueue_kernel";
const static char FixedSqrtINTEL[] = "intel_arbitrary_fixed_sqrt";
const static char FixedRecipINTEL[] = "intel_arbitrary_fixed_recip";
const static char FixedRsqrtINTEL[] = "intel_arbitrary_fixed_rsqrt";
const static char FixedSinINTEL[] = "intel_arbitrary_fixed_sin";
const static char FixedCosINTEL[] = "intel_arbitrary_fixed_cos";
const static char FixedSinCosINTEL[] = "intel_arbitrary_fixed_sincos";
const static char FixedSinPiINTEL[] = "intel_arbitrary_fixed_sinpi";
const static char FixedCosPiINTEL[] = "intel_arbitrary_fixed_cospi";
const static char FixedSinCosPiINTEL[] = "intel_arbitrary_fixed_sincospi";
const static char FixedLogINTEL[] = "intel_arbitrary_fixed_log";
const static char FixedExpINTEL[] = "intel_arbitrary_fixed_exp";
const static char FMax[] = "fmax";
const static char FMin[] = "fmin";
const static char FPGARegIntel[] = "__builtin_intel_fpga_reg";
Expand Down Expand Up @@ -1109,6 +1120,26 @@ template <> inline void LLVMSPIRVAtomicRmwOpCodeMap::init() {
add(llvm::AtomicRMWInst::UMin, OpAtomicUMin);
}

class SPIRVFixedPointIntelInst;
template <>
inline void SPIRVMap<std::string, Op, SPIRVFixedPointIntelInst>::init() {
#define _SPIRV_OP(x, y) add("intel_arbitrary_fixed_" #x, OpFixed##y##INTEL);
_SPIRV_OP(sqrt, Sqrt)
_SPIRV_OP(recip, Recip)
_SPIRV_OP(rsqrt, Rsqrt)
_SPIRV_OP(sin, Sin)
_SPIRV_OP(cos, Cos)
_SPIRV_OP(sincos, SinCos)
_SPIRV_OP(sinpi, SinPi)
_SPIRV_OP(cospi, CosPi)
_SPIRV_OP(sincospi, SinCosPi)
_SPIRV_OP(log, Log)
_SPIRV_OP(exp, Exp)
#undef _SPIRV_OP
}
typedef SPIRVMap<std::string, Op, SPIRVFixedPointIntelInst>
SPIRVFixedPointIntelMap;

} // namespace SPIRV

#endif // SPIRV_OCLUTIL_H
71 changes: 71 additions & 0 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2375,6 +2375,19 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
auto *IntrinsicCall = Builder.CreateIntrinsic(IID, RetTy, Args);
return mapValue(BV, IntrinsicCall);
}
case OpFixedSqrtINTEL:
case OpFixedRecipINTEL:
case OpFixedRsqrtINTEL:
case OpFixedSinINTEL:
case OpFixedCosINTEL:
case OpFixedSinCosINTEL:
case OpFixedSinPiINTEL:
case OpFixedCosPiINTEL:
case OpFixedSinCosPiINTEL:
case OpFixedLogINTEL:
case OpFixedExpINTEL:
return mapValue(
BV, transFixedPointInst(static_cast<SPIRVInstruction *>(BV), BB));
default: {
auto OC = BV->getOpCode();
if (isSPIRVCmpInstTransToLLVMInst(static_cast<SPIRVInstruction *>(BV))) {
Expand All @@ -2399,6 +2412,64 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
}
}

CallInst *SPIRVToLLVM::transFixedPointInst(SPIRVInstruction *BI,
BasicBlock *BB) {
// LLVM fixed point functions return value:
// iN
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is N?

// Arguments:
// A(iN), S(i1), I(i32), rI(i32), Quantization(i32), Overflow(i32)

// SPIR-V fixed point instruction contains:
// <id>ResTy Res<id> <id>InTy In<id> \
// Literal S Literal I Literal rI Literal Q Literal O

Type *RetTy = transType(BI->getType());

auto Inst = static_cast<SPIRVFixedPointIntelInst *>(BI);
Type *InTy = transType(Inst->getOperand(1)->getType());

IntegerType *Int32Ty = IntegerType::get(*Context, 32);
IntegerType *Int1Ty = IntegerType::get(*Context, 1);

SmallVector<Type *, 7> ArgTys = {InTy, Int1Ty, Int32Ty,
Int32Ty, Int32Ty, Int32Ty};
FunctionType *FT = FunctionType::get(RetTy, ArgTys, false);

// Add meaningful suffix at the end of the function name to avoid ascending
// numerical suffixes. It is useful in situations, where the same function is
// called twice or more in one basic block. So, the function name is formed in
// the following way: [FuncName].[ReturnTy].[InputTy]
std::stringstream Suffix;
Suffix << ".i" << RetTy->getIntegerBitWidth() << ".i"
<< InTy->getIntegerBitWidth();

Op OpCode = Inst->getOpCode();
std::string FuncName = SPIRVFixedPointIntelMap::rmap(OpCode) + Suffix.str();

FunctionCallee FCallee = M->getOrInsertFunction(FuncName, FT);

if (Function *Fn = dyn_cast<Function>(FCallee.getCallee())) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check if this is Function*? What if this is not so?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We check that it is a Function* with dyn_cast<Function>. Probably we might want to check that FCallee.getCallee() doesn't return nullptr. We should use dyn_cast_or_null in this case.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, actually we expect that it will be always Function* because we insert function call on the line above.
I would rather use just cast<Function> call without an if check.

Fn->setCallingConv(CallingConv::SPIR_FUNC);
if (isFuncNoUnwind())
Fn->addFnAttr(Attribute::NoUnwind);
}

// Words contain:
// <id>InTy In<id> Literal S Literal I Literal rI Literal Q Literal O
auto Words = Inst->getOpWords();
std::vector<Value *> Args = {
transValue(Inst->getOperand(1), BB->getParent(), BB) /* A - input */,
ConstantInt::get(Int1Ty, Words[2]) /* S - indicator of signedness */,
ConstantInt::get(Int32Ty,
Words[3]) /* I - fixed-point location of the input */,
ConstantInt::get(Int32Ty,
Words[4]) /* rI - fixed-point location of the result*/,
ConstantInt::get(Int32Ty, Words[5]) /* Quantization mode */,
ConstantInt::get(Int32Ty, Words[6]) /* Overflow mode */};

return CallInst::Create(FCallee, Args, "", BB);
}

template <class SourceTy, class FuncTy>
bool SPIRVToLLVM::foreachFuncCtlMask(SourceTy Source, FuncTy Func) {
SPIRVWord FCM = Source->getFuncCtlMask();
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/SPIRVReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class SPIRVToLLVM {
Value *transAsmINTEL(SPIRVAsmINTEL *BA);
CallInst *transAsmCallINTEL(SPIRVAsmCallINTEL *BI, Function *F,
BasicBlock *BB);
CallInst *transFixedPointInst(SPIRVInstruction *BI, BasicBlock *BB);
bool transNonTemporalMetadata(Instruction *I);
bool transSourceLanguage();
bool transSourceExtension();
Expand Down
44 changes: 44 additions & 0 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2570,6 +2570,11 @@ SPIRVInstruction *LLVMToSPIRV::transBuiltinToInst(StringRef DemangledName,
!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_blocking_pipes))
return nullptr;

if (OpFixedSqrtINTEL <= OC && OC <= OpFixedExpINTEL &&
!BM->isAllowedToUseExtension(
ExtensionID::SPV_INTEL_arbitrary_precision_fixed_point))
return nullptr;

auto Inst = transBuiltinToInstWithoutDecoration(OC, CI, BB);
addDecorations(Inst, Dec);
return Inst;
Expand Down Expand Up @@ -2867,6 +2872,45 @@ LLVMToSPIRV::transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI,
transValue(Image, BB),
transValue(Sampler, BB), BB);
}
case OpFixedSqrtINTEL:
case OpFixedRecipINTEL:
case OpFixedRsqrtINTEL:
case OpFixedSinINTEL:
case OpFixedCosINTEL:
case OpFixedSinCosINTEL:
case OpFixedSinPiINTEL:
case OpFixedCosPiINTEL:
case OpFixedSinCosPiINTEL:
case OpFixedLogINTEL:
case OpFixedExpINTEL: {
// LLVM fixed point functions return value:
// iN
// Arguments:
// A(iN), S(i1), I(i32), rI(i32), Quantization(i32), Overflow(i32)
// where A - integer input of any width.

// SPIR-V fixed point instruction contains:
// <id>ResTy Res<id> <id>InTy In<id> \
// Literal S Literal I Literal rI Literal Q Literal O

Type *ResTy = CI->getType();
SPIRVValue *Input =
transValue(CI->getOperand(0) /* A - integer input of any width */, BB);

std::vector<Value *> Operands = {
CI->getOperand(1) /* S - bool value, indicator of signedness */,
CI->getOperand(2) /* I - location of the fixed-point of the input */,
CI->getOperand(3) /* rI - location of the fixed-point of the result*/,
CI->getOperand(4) /* Quantization mode */,
CI->getOperand(5) /* Overflow mode */};
std::vector<SPIRVWord> Literals;
for (auto *O : Operands) {
Literals.push_back(cast<llvm::ConstantInt>(O)->getZExtValue());
}

return BM->addFixedPointIntelInst(OC, transType(ResTy), Input, Literals,
BB);
}
default: {
if (isCvtOpCode(OC) && OC != OpGenericCastToPtrExplicit) {
return BM->addUnaryInst(OC, transType(CI->getType()),
Expand Down
27 changes: 27 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2660,6 +2660,33 @@ _SPIRV_OP(ReadPipeBlockingINTEL, false, 5)
_SPIRV_OP(WritePipeBlockingINTEL, false, 5)
#undef _SPIRV_OP

class SPIRVFixedPointIntelInst : public SPIRVInstTemplateBase {
protected:
SPIRVCapVec getRequiredCapability() const override {
return getVec(CapabilityArbitraryPrecisionFixedPointINTEL);
}

SPIRVExtSet getRequiredExtensions() const override {
return getSet(ExtensionID::SPV_INTEL_arbitrary_precision_fixed_point);
}
};

#define _SPIRV_OP(x, ...) \
typedef SPIRVInstTemplate<SPIRVFixedPointIntelInst, Op##x, __VA_ARGS__> \
SPIRV##x;
_SPIRV_OP(FixedSqrtINTEL, true, 10)
_SPIRV_OP(FixedRecipINTEL, true, 10)
_SPIRV_OP(FixedRsqrtINTEL, true, 10)
_SPIRV_OP(FixedSinINTEL, true, 10)
_SPIRV_OP(FixedCosINTEL, true, 10)
_SPIRV_OP(FixedSinCosINTEL, true, 10)
_SPIRV_OP(FixedSinPiINTEL, true, 10)
_SPIRV_OP(FixedCosPiINTEL, true, 10)
_SPIRV_OP(FixedSinCosPiINTEL, true, 10)
_SPIRV_OP(FixedLogINTEL, true, 10)
_SPIRV_OP(FixedExpINTEL, true, 10)
#undef _SPIRV_OP

class SPIRVAtomicInstBase : public SPIRVInstTemplateBase {
public:
SPIRVCapVec getRequiredCapability() const override {
Expand Down
12 changes: 12 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ inline bool isValid(spv::Capability V) {
case CapabilityUnstructuredLoopControlsINTEL:
case CapabilityKernelAttributesINTEL:
case CapabilityFPGAKernelAttributesINTEL:
case CapabilityArbitraryPrecisionFixedPointINTEL:
return true;
default:
return false;
Expand Down Expand Up @@ -870,6 +871,17 @@ inline bool isValid(spv::Op V) {
case OpGroupSMax:
case OpReadPipe:
case OpWritePipe:
case OpFixedSqrtINTEL:
case OpFixedRecipINTEL:
case OpFixedRsqrtINTEL:
case OpFixedSinINTEL:
case OpFixedCosINTEL:
case OpFixedSinCosINTEL:
case OpFixedSinPiINTEL:
case OpFixedCosPiINTEL:
case OpFixedSinCosPiINTEL:
case OpFixedLogINTEL:
case OpFixedExpINTEL:
case OpReadPipeBlockingINTEL:
case OpWritePipeBlockingINTEL:
case OpReservedReadPipe:
Expand Down
13 changes: 13 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@ class SPIRVModuleImpl : public SPIRVModule {
addLoopControlINTELInst(SPIRVWord LoopControl,
std::vector<SPIRVWord> LoopControlParameters,
SPIRVBasicBlock *BB) override;
SPIRVInstruction *addFixedPointIntelInst(Op OC, SPIRVType *ResTy,
SPIRVValue *Input,
const std::vector<SPIRVWord> &Ops,
SPIRVBasicBlock *BB) override;
SPIRVInstruction *addSelectionMergeInst(SPIRVId MergeBlock,
SPIRVWord SelectionControl,
SPIRVBasicBlock *BB) override;
Expand Down Expand Up @@ -1410,6 +1414,15 @@ SPIRVInstruction *SPIRVModuleImpl::addLoopControlINTELInst(
const_cast<SPIRVInstruction *>(BB->getTerminateInstr()));
}

SPIRVInstruction *SPIRVModuleImpl::addFixedPointIntelInst(
Op OC, SPIRVType *ResTy, SPIRVValue *Input,
const std::vector<SPIRVWord> &Ops, SPIRVBasicBlock *BB) {
std::vector<SPIRVWord> TheOps =
getVec(Input->getType()->getId(), getVec(Input->getId(), Ops));
return addInstruction(
SPIRVInstTemplateBase::create(OC, ResTy, getId(), TheOps, BB, this), BB);
}

SPIRVInstruction *
SPIRVModuleImpl::addPtrAccessChainInst(SPIRVType *Type, SPIRVValue *Base,
std::vector<SPIRVValue *> Indices,
Expand Down
4 changes: 4 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ class SPIRVModule {
addLoopControlINTELInst(SPIRVWord LoopControl,
std::vector<SPIRVWord> LoopControlParameters,
SPIRVBasicBlock *BB) = 0;
virtual SPIRVInstruction *
addFixedPointIntelInst(Op OC, SPIRVType *ResTy, SPIRVValue *Input,
const std::vector<SPIRVWord> &Ops,
SPIRVBasicBlock *BB) = 0;
virtual SPIRVInstruction *addStoreInst(SPIRVValue *, SPIRVValue *,
const std::vector<SPIRVWord> &,
SPIRVBasicBlock *) = 0;
Expand Down
2 changes: 2 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,8 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
add(CapabilityIndirectReferencesINTEL, "IndirectReferencesINTEL");
add(CapabilityKernelAttributesINTEL, "KernelAttributesINTEL");
add(CapabilityFPGAKernelAttributesINTEL, "FPGAKernelAttributesINTEL");
add(CapabilityArbitraryPrecisionFixedPointINTEL,
"ArbitraryPrecisionFixedPointINTEL");
add(CapabilityIOPipeINTEL, "IOPipeINTEL");
add(CapabilityOptimizationHintsINTEL, "OptimizationHintsINTEL");
add(CapabilityGroupNonUniform, "GroupNonUniform");
Expand Down
11 changes: 11 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,17 @@ _SPIRV_OP(SubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, 5814)
_SPIRV_OP(SubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, 5815)
_SPIRV_OP(SubgroupAvcSicGetInterRawSadsINTEL, 5816)
_SPIRV_OP(LoopControlINTEL, 5887)
_SPIRV_OP(FixedSqrtINTEL, 5923)
_SPIRV_OP(FixedRecipINTEL, 5924)
_SPIRV_OP(FixedRsqrtINTEL, 5925)
_SPIRV_OP(FixedSinINTEL, 5926)
_SPIRV_OP(FixedCosINTEL, 5927)
_SPIRV_OP(FixedSinCosINTEL, 5928)
_SPIRV_OP(FixedSinPiINTEL, 5929)
_SPIRV_OP(FixedCosPiINTEL, 5930)
_SPIRV_OP(FixedSinCosPiINTEL, 5931)
_SPIRV_OP(FixedLogINTEL, 5932)
_SPIRV_OP(FixedExpINTEL, 5933)
_SPIRV_OP(PtrCastToCrossWorkgroupINTEL, 5934)
_SPIRV_OP(CrossWorkgroupCastToPtrINTEL, 5938)
_SPIRV_OP(ReadPipeBlockingINTEL, 5946)
Expand Down
12 changes: 12 additions & 0 deletions lib/SPIRV/libSPIRV/spirv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,7 @@ enum Capability {
CapabilityFPGARegINTEL = 5948,
CapabilityKernelAttributesINTEL = 5892,
CapabilityFPGAKernelAttributesINTEL = 5897,
CapabilityArbitraryPrecisionFixedPointINTEL = 5922,
CapabilityUSMStorageClassesINTEL = 5935,
CapabilityIOPipeINTEL = 5943,
CapabilityMax = 0x7fffffff,
Expand Down Expand Up @@ -1496,6 +1497,17 @@ enum Op {
OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
OpLoopControlINTEL = 5887,
OpFixedSqrtINTEL = 5923,
OpFixedRecipINTEL = 5924,
OpFixedRsqrtINTEL = 5925,
OpFixedSinINTEL = 5926,
OpFixedCosINTEL = 5927,
OpFixedSinCosINTEL = 5928,
OpFixedSinPiINTEL = 5929,
OpFixedCosPiINTEL = 5930,
OpFixedSinCosPiINTEL = 5931,
OpFixedLogINTEL = 5932,
OpFixedExpINTEL = 5933,
OpPtrCastToCrossWorkgroupINTEL = 5934,
OpCrossWorkgroupCastToPtrINTEL = 5938,
OpReadPipeBlockingINTEL = 5946,
Expand Down
Loading