Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
62 changes: 62 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,55 @@ 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);

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

SmallVector<Type *, 7> ArgTys = {transType(Inst->getOperand(1)->getType()),
Int1Ty,
Int32Ty,
Int32Ty,
Int32Ty,
Int32Ty};

FunctionType *FT = FunctionType::get(RetTy, ArgTys, false);

Op OpCode = Inst->getOpCode();
Function *Func = Function::Create(FT, GlobalValue::ExternalLinkage,

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.

Do you have a test where the same fixed point funciton/opcode is encountered twice? I would expect that Funciton::Create will declare the same buit-in each time it is called and it will add .1, .2, etc. suffixes to declaration name. You probably interested in llvm::Module::getOrInsertFunction`

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, that's a good point, thanks! I will fix that and add the appropriate test case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This getOrInsertFunction is not perfect, though. If the same function is called twice - it works fine, but if the same function has different signatures and return types - a huge bitcast is being created:
call i13 bitcast (i5 (i13, i1, i32, i32, i32, i32)* @intel_arbitrary_fixed_sqrt to i13 (i5, i1, i32, i32, i32, i32)*)(i5 %5, i1 false, i32 2, i32 2, i32 0, i32 0)
Not sure what is better - bitcast or .N at the end of the function name. What do you think of this?

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.

It depends on what can be handled by the consumer of that LLVM IR which is translated from the SPIR-V.

I guess that both variants are not really acceptable. Usually, such overloads are distinguished by mangling and .1, .2 is some kind of it, also it is common that LLVM IR representation after the translation is similar to/the same as LLVM IR representation before translation - probably this is a way you need to go?

SPIRVFixedPointIntelMap::rmap(OpCode), M);
Func->setCallingConv(CallingConv::SPIR_FUNC);
if (isFuncNoUnwind())
Func->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(Func, 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