Skip to content

Commit 091c366

Browse files
MrSidimsAlexeySotkin
authored andcommitted
Implement SPV_INTEL_token_type extension
This extension adds a type-declaration instruction OpTypeTokenINTEL, which is an analog of LLVM's type token. This type specifies IDs of entry points and exit points of certain IL constructs, for example it can be useful for exception handling representation in IL. Spec: intel/llvm#3788 Signed-off-by: Dmitry Sidorov <dmitry.sidorov@intel.com>
1 parent e303a5f commit 091c366

File tree

13 files changed

+136
-3
lines changed

13 files changed

+136
-3
lines changed

include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ EXT(SPV_INTEL_long_constant_composite)
3838
EXT(SPV_INTEL_optnone)
3939
EXT(SPV_INTEL_memory_access_aliasing)
4040
EXT(SPV_INTEL_fpga_invocation_pipelining_attributes)
41+
EXT(SPV_INTEL_token_type)

lib/SPIRV/SPIRVReader.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ Type *SPIRVToLLVM::transType(SPIRVType *T, bool IsClassMember) {
470470

471471
SPIRVDBG(spvdbgs() << "[transType] " << *T << " -> ";)
472472
T->validate();
473-
switch (T->getOpCode()) {
473+
switch (static_cast<SPIRVWord>(T->getOpCode())) {
474474
case OpTypeVoid:
475475
return mapType(T, Type::getVoidTy(*Context));
476476
case OpTypeBool:
@@ -482,6 +482,8 @@ Type *SPIRVToLLVM::transType(SPIRVType *T, bool IsClassMember) {
482482
case OpTypeArray:
483483
return mapType(T, ArrayType::get(transType(T->getArrayElementType()),
484484
T->getArrayLength()));
485+
case internal::OpTypeTokenINTEL:
486+
return mapType(T, Type::getTokenTy(*Context));
485487
case OpTypePointer:
486488
return mapType(
487489
T, PointerType::get(

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,16 @@ SPIRVType *LLVMToSPIRVBase::transType(Type *T) {
293293
if (T->isFloatingPointTy())
294294
return mapType(T, BM->addFloatType(T->getPrimitiveSizeInBits()));
295295

296+
if (T->isTokenTy()) {
297+
BM->getErrorLog().checkError(
298+
BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_token_type),
299+
SPIRVEC_RequiresExtension,
300+
"SPV_INTEL_token_type\n"
301+
"NOTE: LLVM module contains token type, which doesn't have analogs in "
302+
"SPIR-V without extensions");
303+
return mapType(T, BM->addTokenTypeINTEL());
304+
}
305+
296306
// A pointer to image or pipe type in LLVM is translated to a SPIRV
297307
// (non-pointer) image or pipe type.
298308
if (T->isPointerTy()) {

lib/SPIRV/libSPIRV/SPIRVErrorEnum.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ _SPIRV_OP(InvalidInstruction, "Can't translate llvm instruction:\n")
1717
_SPIRV_OP(InvalidWordCount,
1818
"Can't encode instruction with word count greater than 65535:\n")
1919
_SPIRV_OP(Requires1_1, "Feature requires SPIR-V 1.1 or greater:")
20+
_SPIRV_OP(RequiresExtension,
21+
"Feature requires the following SPIR-V extension:\n")

lib/SPIRV/libSPIRV/SPIRVModule.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ class SPIRVModuleImpl : public SPIRVModule {
253253
SPIRVTypeVmeImageINTEL *addVmeImageINTELType(SPIRVTypeImage *T) override;
254254
SPIRVTypeBufferSurfaceINTEL *
255255
addBufferSurfaceINTELType(SPIRVAccessQualifierKind Access) override;
256+
SPIRVTypeTokenINTEL *addTokenTypeINTEL() override;
256257

257258
// Constant creation functions
258259
SPIRVInstruction *addBranchInst(SPIRVLabel *, SPIRVBasicBlock *) override;
@@ -946,6 +947,10 @@ SPIRVType *SPIRVModuleImpl::addSubgroupAvcINTELType(Op TheOpCode) {
946947
return addType(new SPIRVTypeSubgroupAvcINTEL(TheOpCode, this, getId()));
947948
}
948949

950+
SPIRVTypeTokenINTEL *SPIRVModuleImpl::addTokenTypeINTEL() {
951+
return addType(new SPIRVTypeTokenINTEL(this, getId()));
952+
}
953+
949954
SPIRVFunction *SPIRVModuleImpl::addFunction(SPIRVFunction *Func) {
950955
FuncVec.push_back(add(Func));
951956
return Func;

lib/SPIRV/libSPIRV/SPIRVModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class SPIRVAsmTargetINTEL;
9494
class SPIRVAsmINTEL;
9595
class SPIRVAsmCallINTEL;
9696
class SPIRVTypeBufferSurfaceINTEL;
97+
class SPIRVTypeTokenINTEL;
9798

9899
typedef SPIRVBasicBlock SPIRVLabel;
99100
struct SPIRVTypeImageDescriptor;
@@ -250,6 +251,7 @@ class SPIRVModule {
250251
virtual SPIRVTypeVmeImageINTEL *addVmeImageINTELType(SPIRVTypeImage *) = 0;
251252
virtual SPIRVTypeBufferSurfaceINTEL *
252253
addBufferSurfaceINTELType(SPIRVAccessQualifierKind Access) = 0;
254+
virtual SPIRVTypeTokenINTEL *addTokenTypeINTEL() = 0;
253255

254256
// Constants creation functions
255257
virtual SPIRVValue *

lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
525525
"MemoryAccessAliasingINTEL");
526526
add(internal::CapabilityFPGAInvocationPipeliningAttributesINTEL,
527527
"FPGAInvocationPipeliningAttributesINTEL");
528+
add(internal::CapabilityTokenTypeINTEL, "TokenTypeINTEL");
528529
}
529530
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)
530531

lib/SPIRV/libSPIRV/SPIRVOpCode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ inline bool isTypeOpCode(Op OpCode) {
210210
unsigned OC = OpCode;
211211
return (OpTypeVoid <= OC && OC <= OpTypePipe) || OC == OpTypePipeStorage ||
212212
isSubgroupAvcINTELTypeOpCode(OpCode) || OC == OpTypeVmeImageINTEL ||
213-
isVCOpCode(OpCode);
213+
isVCOpCode(OpCode) || OC == internal::OpTypeTokenINTEL;
214214
}
215215

216216
inline bool isSpecConstantOpCode(Op OpCode) {

lib/SPIRV/libSPIRV/SPIRVOpCodeEnumInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ _SPIRV_OP_INTERNAL(Forward, internal::OpForward)
44
_SPIRV_OP_INTERNAL(AliasDomainDeclINTEL, internal::OpAliasDomainDeclINTEL)
55
_SPIRV_OP_INTERNAL(AliasScopeDeclINTEL, internal::OpAliasScopeDeclINTEL)
66
_SPIRV_OP_INTERNAL(AliasScopeListDeclINTEL, internal::OpAliasScopeListDeclINTEL)
7+
_SPIRV_OP_INTERNAL(TypeTokenINTEL, internal::OpTypeTokenINTEL)

lib/SPIRV/libSPIRV/SPIRVType.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,5 +1036,26 @@ _SPIRV_OP(AvcImeDualReferenceStreamin)
10361036
_SPIRV_OP(AvcRefResult)
10371037
_SPIRV_OP(AvcSicResult)
10381038
#undef _SPIRV_OP
1039+
1040+
class SPIRVTypeTokenINTEL : public SPIRVType {
1041+
public:
1042+
// Complete constructor
1043+
SPIRVTypeTokenINTEL(SPIRVModule *M, SPIRVId TheId)
1044+
: SPIRVType(M, 2, internal::OpTypeTokenINTEL, TheId) {}
1045+
// Incomplete constructor
1046+
SPIRVTypeTokenINTEL() : SPIRVType(internal::OpTypeTokenINTEL) {}
1047+
1048+
SPIRVCapVec getRequiredCapability() const override {
1049+
return getVec(internal::CapabilityTokenTypeINTEL);
1050+
}
1051+
1052+
llvm::Optional<ExtensionID> getRequiredExtension() const override {
1053+
return ExtensionID::SPV_INTEL_token_type;
1054+
}
1055+
1056+
protected:
1057+
_SPIRV_DEF_ENCDEC1(Id)
1058+
};
1059+
10391060
} // namespace SPIRV
10401061
#endif // SPIRV_LIBSPIRV_SPIRVTYPE_H

lib/SPIRV/libSPIRV/spirv_internal.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ enum InternalOp {
3838
IOpAliasDomainDeclINTEL = 5911,
3939
IOpAliasScopeDeclINTEL = 5912,
4040
IOpAliasScopeListDeclINTEL = 5913,
41+
IOpTypeTokenINTEL = 6113,
4142
IOpPrev = OpMax - 2,
4243
IOpForward
4344
};
@@ -53,7 +54,8 @@ enum InternalDecoration {
5354
enum InternalCapability {
5455
ICapMemoryAccessAliasingINTEL = 5910,
5556
ICapFPGAInvocationPipeliningAttributesINTEL = 5916,
56-
ICapOptNoneINTEL = 6094
57+
ICapOptNoneINTEL = 6094,
58+
ICapTokenTypeINTEL = 6112
5759
};
5860

5961
enum InternalFunctionControlMask { IFunctionControlOptNoneINTELMask = 0x10000 };
@@ -71,6 +73,7 @@ constexpr Op OpAliasDomainDeclINTEL = static_cast<Op>(IOpAliasDomainDeclINTEL);
7173
constexpr Op OpAliasScopeDeclINTEL = static_cast<Op>(IOpAliasScopeDeclINTEL);
7274
constexpr Op OpAliasScopeListDeclINTEL =
7375
static_cast<Op>(IOpAliasScopeListDeclINTEL);
76+
constexpr Op OpTypeTokenINTEL = static_cast<Op>(IOpTypeTokenINTEL);
7477

7578
constexpr Decoration DecorationAliasScopeINTEL =
7679
static_cast<Decoration>(IDecAliasScopeINTEL );
@@ -89,6 +92,8 @@ constexpr Capability CapabilityMemoryAccessAliasingINTEL =
8992
static_cast<Capability>(ICapMemoryAccessAliasingINTEL);
9093
constexpr Capability CapabilityFPGAInvocationPipeliningAttributesINTEL =
9194
static_cast<Capability>(ICapFPGAInvocationPipeliningAttributesINTEL);
95+
constexpr Capability CapabilityTokenTypeINTEL =
96+
static_cast<Capability>(ICapTokenTypeINTEL);
9297

9398
constexpr FunctionControlMask FunctionControlOptNoneINTELMask =
9499
static_cast<FunctionControlMask>(IFunctionControlOptNoneINTELMask);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; Check whether the translator reports an error for a module with token type
2+
; if SPV_INTEL_token_type extension is not used.
3+
4+
; RUN: llvm-as < %s -o %t.bc
5+
; RUN: not llvm-spirv %t.bc 2>&1 --spirv-allow-unknown-intrinsics | FileCheck %s
6+
7+
; CHECK: RequiresExtension: Feature requires the following SPIR-V extension:
8+
; CHECK-NEXT: SPV_INTEL_token_type
9+
; CHECK-NEXT: NOTE: LLVM module contains token type, which doesn't have analogs
10+
; CHECK-SAME: in SPIR-V without extensions
11+
12+
; ModuleID = 'token.bc'
13+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
14+
target triple = "spir-unknown-unknown"
15+
16+
declare token @llvm.tokenfoo()
17+
18+
; Function Attrs: nounwind
19+
define spir_kernel void @foo() #0 !kernel_arg_addr_space !2 !kernel_arg_access_qual !2 !kernel_arg_type !2 !kernel_arg_type_qual !2 !kernel_arg_base_type !2 {
20+
entry:
21+
%tok = call token @llvm.tokenfoo()
22+
ret void
23+
}
24+
25+
attributes #0 = { nounwind }
26+
27+
!spirv.MemoryModel = !{!0}
28+
!opencl.enable.FP_CONTRACT = !{}
29+
!spirv.Source = !{!1}
30+
!opencl.spir.version = !{!0}
31+
!opencl.ocl.version = !{!0}
32+
!opencl.used.extensions = !{!2}
33+
!opencl.used.optional.core.features = !{!2}
34+
!spirv.Generator = !{!3}
35+
36+
!0 = !{i32 1, i32 2}
37+
!1 = !{i32 3, i32 102000}
38+
!2 = !{}
39+
!3 = !{i16 6, i16 14}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; RUN: llvm-as < %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-allow-unknown-intrinsics --spirv-ext=+SPV_INTEL_token_type
3+
; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
4+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
5+
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM
6+
7+
; CHECK-SPIRV: Capability TokenTypeINTEL
8+
; CHECK-SPIRV: Extension "SPV_INTEL_token_type"
9+
; CHECK-SPIRV: Name [[#FUN:]] "llvm.tokenfoo"
10+
; CHECK-SPIRV: TypeTokenINTEL [[#TYPE:]]
11+
; CHECK-SPIRV: TypeFunction [[#FUN_TYPE:]] [[#TYPE]]
12+
; CHECK-SPIRV: Function {{.*}} [[#FUN]] {{.*}} [[#FUN_TYPE]]
13+
14+
15+
; ModuleID = 'token.bc'
16+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
17+
target triple = "spir-unknown-unknown"
18+
19+
; CHECK-LLVM: declare token @llvm.tokenfoo()
20+
declare token @llvm.tokenfoo()
21+
22+
; Function Attrs: nounwind
23+
define spir_kernel void @foo() #0 !kernel_arg_addr_space !2 !kernel_arg_access_qual !2 !kernel_arg_type !2 !kernel_arg_type_qual !2 !kernel_arg_base_type !2 {
24+
entry:
25+
; CHECK-LLVM: call token @llvm.tokenfoo()
26+
%tok = call token @llvm.tokenfoo()
27+
ret void
28+
}
29+
30+
attributes #0 = { nounwind }
31+
32+
!spirv.MemoryModel = !{!0}
33+
!opencl.enable.FP_CONTRACT = !{}
34+
!spirv.Source = !{!1}
35+
!opencl.spir.version = !{!0}
36+
!opencl.ocl.version = !{!0}
37+
!opencl.used.extensions = !{!2}
38+
!opencl.used.optional.core.features = !{!2}
39+
!spirv.Generator = !{!3}
40+
41+
!0 = !{i32 1, i32 2}
42+
!1 = !{i32 3, i32 102000}
43+
!2 = !{}
44+
!3 = !{i16 6, i16 14}

0 commit comments

Comments
 (0)