Skip to content

Commit 17174ac

Browse files
authored
Support for SPV_INTEL_cache_controls (#2145)
Specification: KhronosGroup/SPIRV-Registry#216 Cherry-pick of #2140
1 parent 854179a commit 17174ac

File tree

12 files changed

+267
-14
lines changed

12 files changed

+267
-14
lines changed

docs/SPIRVRepresentationInLLVM.rst

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,14 +411,14 @@ For example:
411411
are translated for image types, but they should be encoded in LLVM IR type name
412412
rather than function metadata.
413413

414-
Function parameter and global variable decoration through metadata
414+
Function parameter, instruction and global variable decoration through metadata
415415
------------------------------------------------------------------
416416

417-
Both function parameters and global variables can be decorated using LLVM
417+
Function parameters, instructions and global variables can be decorated using LLVM
418418
metadata through the metadata names ``spirv.ParameterDecorations`` and
419419
``spirv.Decorations`` respectively. ``spirv.ParameterDecorations`` must be tied
420420
to the kernel function while ``spirv.Decorations`` is tied directly to the
421-
global variable.
421+
instruction or global variable.
422422

423423
A "decoration-node" is a metadata node consisting of one or more operands. The
424424
first operand is an integer literal representing the SPIR-V decoration
@@ -434,7 +434,7 @@ decoration-nodes.
434434
references to decoration-lists, where N is the number of arguments of the
435435
function the metadata is tied to.
436436

437-
``spirv.Decorations`` example:
437+
``spirv.Decorations`` applied on a global variable example:
438438

439439
.. code-block:: llvm
440440
@@ -447,6 +447,18 @@ function the metadata is tied to.
447447
decorates a global variable ``v`` with ``Constant`` and ``LinkageAttributes``
448448
with extra operands ``"v"`` and ``Export`` in SPIR-V.
449449

450+
``spirv.Decorations`` applied on an instruction example:
451+
452+
.. code-block:: llvm
453+
454+
%idx = getelementptr inbounds i32, ptr addrspace(1) %b, i64 1, !spirv.Decorations !1
455+
...
456+
!1 = !{!2}
457+
!2 = !{i32 6442, i32 1, i32 2} ; {CacheControlLoadINTEL, CacheLevel=1, Cached}
458+
459+
decorates getelementptr instruction with CacheControlLoadINTEL decoration with
460+
extra operands ``i32 1`` and ``i32 2``.
461+
450462
``spirv.ParameterDecorations`` example:
451463

452464
.. code-block:: llvm

include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ EXT(SPV_INTEL_tensor_float32_rounding)
6262
EXT(SPV_EXT_relaxed_printf_string_address_space)
6363
EXT(SPV_INTEL_fpga_argument_interfaces)
6464
EXT(SPV_INTEL_fpga_latency_control)
65+
EXT(SPV_INTEL_cache_controls)

lib/SPIRV/SPIRVReader.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3866,17 +3866,22 @@ transDecorationsToMetadataList(llvm::LLVMContext *Context,
38663866
return MDNode::get(*Context, MDs);
38673867
}
38683868

3869-
void SPIRVToLLVM::transVarDecorationsToMetadata(SPIRVValue *BV, Value *V) {
3870-
if (!BV->isVariable())
3869+
void SPIRVToLLVM::transDecorationsToMetadata(SPIRVValue *BV, Value *V) {
3870+
if (!BV->isVariable() && !BV->isInst())
38713871
return;
38723872

3873-
if (auto *GV = dyn_cast<GlobalVariable>(V)) {
3873+
auto SetDecorationsMetadata = [&](auto V) {
38743874
std::vector<SPIRVDecorate const *> Decorates = BV->getDecorations();
38753875
if (!Decorates.empty()) {
38763876
MDNode *MDList = transDecorationsToMetadataList(Context, Decorates);
3877-
GV->setMetadata(SPIRV_MD_DECORATIONS, MDList);
3877+
V->setMetadata(SPIRV_MD_DECORATIONS, MDList);
38783878
}
3879-
}
3879+
};
3880+
3881+
if (auto *GV = dyn_cast<GlobalVariable>(V))
3882+
SetDecorationsMetadata(GV);
3883+
else if (auto *I = dyn_cast<Instruction>(V))
3884+
SetDecorationsMetadata(I);
38803885
}
38813886

38823887
bool SPIRVToLLVM::transDecoration(SPIRVValue *BV, Value *V) {
@@ -3888,7 +3893,7 @@ bool SPIRVToLLVM::transDecoration(SPIRVValue *BV, Value *V) {
38883893

38893894
// Decoration metadata is only enabled in SPIR-V friendly mode
38903895
if (BM->getDesiredBIsRepresentation() == BIsRepresentation::SPIRVFriendlyIR)
3891-
transVarDecorationsToMetadata(BV, V);
3896+
transDecorationsToMetadata(BV, V);
38923897

38933898
DbgTran->transDbgInfo(BV, V);
38943899
return true;

lib/SPIRV/SPIRVReader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class SPIRVToLLVM : private BuiltinCallHelper {
256256
SmallVectorImpl<Function *> &Funcs);
257257
void transIntelFPGADecorations(SPIRVValue *BV, Value *V);
258258
void transMemAliasingINTELDecorations(SPIRVValue *BV, Value *V);
259-
void transVarDecorationsToMetadata(SPIRVValue *BV, Value *V);
259+
void transDecorationsToMetadata(SPIRVValue *BV, Value *V);
260260
void transFunctionDecorationsToMetadata(SPIRVFunction *BF, Function *F);
261261
void
262262
transFunctionPointerCallArgumentAttributes(SPIRVValue *BV, CallInst *CI,

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2604,6 +2604,48 @@ static void transMetadataDecorations(Metadata *MD, SPIRVEntry *Target) {
26042604
new SPIRVDecorateImplementInCSRINTEL(Target, Value->getZExtValue()));
26052605
break;
26062606
}
2607+
case spv::internal::DecorationCacheControlLoadINTEL: {
2608+
ErrLog.checkError(
2609+
NumOperands == 3, SPIRVEC_InvalidLlvmModule,
2610+
"CacheControlLoadINTEL requires exactly 2 extra operands");
2611+
auto *CacheLevel =
2612+
mdconst::dyn_extract<ConstantInt>(DecoMD->getOperand(1));
2613+
auto *CacheControl =
2614+
mdconst::dyn_extract<ConstantInt>(DecoMD->getOperand(2));
2615+
ErrLog.checkError(CacheLevel, SPIRVEC_InvalidLlvmModule,
2616+
"CacheControlLoadINTEL cache level operand is required "
2617+
"to be an integer");
2618+
ErrLog.checkError(CacheControl, SPIRVEC_InvalidLlvmModule,
2619+
"CacheControlLoadINTEL cache control operand is "
2620+
"required to be an integer");
2621+
2622+
Target->addDecorate(new SPIRVDecorateCacheControlLoadINTEL(
2623+
Target, CacheLevel->getZExtValue(),
2624+
static_cast<internal::LoadCacheControlINTEL>(
2625+
CacheControl->getZExtValue())));
2626+
break;
2627+
}
2628+
case spv::internal::DecorationCacheControlStoreINTEL: {
2629+
ErrLog.checkError(
2630+
NumOperands == 3, SPIRVEC_InvalidLlvmModule,
2631+
"CacheControlStoreINTEL requires exactly 2 extra operands");
2632+
auto *CacheLevel =
2633+
mdconst::dyn_extract<ConstantInt>(DecoMD->getOperand(1));
2634+
auto *CacheControl =
2635+
mdconst::dyn_extract<ConstantInt>(DecoMD->getOperand(2));
2636+
ErrLog.checkError(CacheLevel, SPIRVEC_InvalidLlvmModule,
2637+
"CacheControlStoreINTEL cache level operand is "
2638+
"required to be an integer");
2639+
ErrLog.checkError(CacheControl, SPIRVEC_InvalidLlvmModule,
2640+
"CacheControlStoreINTEL cache control operand is "
2641+
"required to be an integer");
2642+
2643+
Target->addDecorate(new SPIRVDecorateCacheControlStoreINTEL(
2644+
Target, CacheLevel->getZExtValue(),
2645+
static_cast<internal::StoreCacheControlINTEL>(
2646+
CacheControl->getZExtValue())));
2647+
break;
2648+
}
26072649
default: {
26082650
if (NumOperands == 1) {
26092651
Target->addDecorate(new SPIRVDecorate(DecoKind, Target));
@@ -2691,9 +2733,12 @@ bool LLVMToSPIRVBase::transDecoration(Value *V, SPIRVValue *BV) {
26912733
BV->setFPFastMathMode(M);
26922734
}
26932735
}
2694-
if (Instruction *Inst = dyn_cast<Instruction>(V))
2736+
if (Instruction *Inst = dyn_cast<Instruction>(V)) {
26952737
if (shouldTryToAddMemAliasingDecoration(Inst))
26962738
transMemAliasingINTELDecorations(Inst, BV);
2739+
if (auto *IDecoMD = Inst->getMetadata(SPIRV_MD_DECORATIONS))
2740+
transMetadataDecorations(IDecoMD, BV);
2741+
}
26972742

26982743
if (auto *CI = dyn_cast<CallInst>(V)) {
26992744
auto OC = BV->getOpCode();

lib/SPIRV/libSPIRV/SPIRVDecorate.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ class SPIRVDecorate : public SPIRVDecorateGeneric {
201201
case DecorationLatencyControlLabelINTEL:
202202
case DecorationLatencyControlConstraintINTEL:
203203
return ExtensionID::SPV_INTEL_fpga_latency_control;
204+
case internal::DecorationCacheControlLoadINTEL:
205+
case internal::DecorationCacheControlStoreINTEL:
206+
return ExtensionID::SPV_INTEL_cache_controls;
204207
default:
205208
return {};
206209
}
@@ -785,6 +788,37 @@ class SPIRVDecorateImplementInCSRINTEL : public SPIRVDecorate {
785788
Value) {}
786789
};
787790

791+
class SPIRVDecorateCacheControlLoadINTEL : public SPIRVDecorate {
792+
public:
793+
// Complete constructor for SPIRVDecorateCacheControlLoadINTEL
794+
SPIRVDecorateCacheControlLoadINTEL(
795+
SPIRVEntry *TheTarget, SPIRVWord CacheLevel,
796+
spv::internal::LoadCacheControlINTEL CacheControl)
797+
: SPIRVDecorate(spv::internal::DecorationCacheControlLoadINTEL, TheTarget,
798+
CacheLevel, static_cast<SPIRVWord>(CacheControl)){};
799+
800+
SPIRVWord getCacheLevel() const { return Literals.at(0); };
801+
spv::internal::LoadCacheControlINTEL getCacheControl() const {
802+
return static_cast<spv::internal::LoadCacheControlINTEL>(Literals.at(1));
803+
};
804+
};
805+
806+
class SPIRVDecorateCacheControlStoreINTEL : public SPIRVDecorate {
807+
public:
808+
// Complete constructor for SPIRVDecorateCacheControlStoreINTEL
809+
SPIRVDecorateCacheControlStoreINTEL(
810+
SPIRVEntry *TheTarget, SPIRVWord CacheLevel,
811+
spv::internal::StoreCacheControlINTEL CacheControl)
812+
: SPIRVDecorate(spv::internal::DecorationCacheControlStoreINTEL,
813+
TheTarget, CacheLevel,
814+
static_cast<SPIRVWord>(CacheControl)){};
815+
816+
SPIRVWord getCacheLevel() const { return Literals.at(0); };
817+
spv::internal::StoreCacheControlINTEL getCacheControl() const {
818+
return static_cast<spv::internal::StoreCacheControlINTEL>(Literals.at(1));
819+
};
820+
};
821+
788822
} // namespace SPIRV
789823

790824
#endif // SPIRV_LIBSPIRV_SPIRVDECORATE_H

lib/SPIRV/libSPIRV/SPIRVEnum.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,10 @@ template <> inline void SPIRVMap<Decoration, SPIRVCapVec>::init() {
471471
{internal::CapabilityGlobalVariableDecorationsINTEL});
472472
ADD_VEC_INIT(internal::DecorationArgumentAttributeINTEL,
473473
{CapabilityFunctionPointersINTEL});
474+
ADD_VEC_INIT(internal::DecorationCacheControlLoadINTEL,
475+
{internal::CapabilityCacheControlsINTEL});
476+
ADD_VEC_INIT(internal::DecorationCacheControlStoreINTEL,
477+
{internal::CapabilityCacheControlsINTEL});
474478
ADD_VEC_INIT(DecorationConduitKernelArgumentINTEL,
475479
{CapabilityFPGAArgumentInterfacesINTEL});
476480
ADD_VEC_INIT(DecorationRegisterMapKernelArgumentINTEL,

lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ template <> inline void SPIRVMap<Decoration, std::string>::init() {
206206
add(internal::DecorationInitModeINTEL, "InitModeINTEL");
207207
add(internal::DecorationImplementInCSRINTEL, "ImplementInCSRINTEL");
208208
add(internal::DecorationArgumentAttributeINTEL, "ArgumentAttributeINTEL");
209+
add(internal::DecorationCacheControlLoadINTEL, "CacheControlLoadINTEL");
210+
add(internal::DecorationCacheControlStoreINTEL, "CacheControlStoreINTEL");
209211

210212
add(DecorationMax, "Max");
211213
}
@@ -645,6 +647,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
645647
"JointMatrixPackedInt2ComponentTypeINTEL");
646648
add(internal::CapabilityJointMatrixPackedInt4ComponentTypeINTEL,
647649
"JointMatrixPackedInt4ComponentTypeINTEL");
650+
add(internal::CapabilityCacheControlsINTEL, "CacheControlsINTEL");
648651
}
649652
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)
650653

lib/SPIRV/libSPIRV/spirv_internal.hpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ enum InternalDecoration {
8787
IDecHostAccessINTEL = 6147,
8888
IDecInitModeINTEL = 6148,
8989
IDecImplementInCSRINTEL = 6149,
90-
IDecArgumentAttributeINTEL = 6409
90+
IDecArgumentAttributeINTEL = 6409,
91+
IDecCacheControlLoadINTEL = 6442,
92+
IDecCacheControlStoreINTEL = 6443
9193
};
9294

9395
enum InternalCapability {
@@ -106,7 +108,8 @@ enum InternalCapability {
106108
ICapabilityJointMatrixTF32ComponentTypeINTEL = 6436,
107109
ICapabilityJointMatrixBF16ComponentTypeINTEL = 6437,
108110
ICapabilityJointMatrixPackedInt2ComponentTypeINTEL = 6438,
109-
ICapabilityJointMatrixPackedInt4ComponentTypeINTEL = 6439
111+
ICapabilityJointMatrixPackedInt4ComponentTypeINTEL = 6439,
112+
ICapabilityCacheControlsINTEL = 6441
110113
};
111114

112115
enum InternalFunctionControlMask { IFunctionControlOptNoneINTELMask = 0x10000 };
@@ -140,6 +143,21 @@ enum InternalBuiltIn {
140143
IBuiltInGlobalHWThreadIDINTEL = 6136,
141144
};
142145

146+
enum class LoadCacheControlINTEL {
147+
Uncached = 0,
148+
Cached = 1,
149+
Streaming = 2,
150+
InvalidateAfterRead = 3,
151+
ConstCached = 4
152+
};
153+
154+
enum class StoreCacheControlINTEL {
155+
Uncached = 0,
156+
WriteThrough = 1,
157+
WriteBack = 2,
158+
Streaming = 3
159+
};
160+
143161
#define _SPIRV_OP(x, y) constexpr x x##y = static_cast<x>(I##x##y);
144162
_SPIRV_OP(Capability, JointMatrixINTEL)
145163
_SPIRV_OP(Capability, JointMatrixWIInstructionsINTEL)
@@ -172,6 +190,8 @@ _SPIRV_OP(Op, MaskedScatterINTEL)
172190

173191
_SPIRV_OP(Capability, TensorFloat32RoundingINTEL)
174192
_SPIRV_OP(Op, RoundFToTF32INTEL)
193+
194+
_SPIRV_OP(Capability, CacheControlsINTEL)
175195
#undef _SPIRV_OP
176196

177197
constexpr SourceLanguage SourceLanguagePython =
@@ -233,6 +253,10 @@ constexpr Decoration DecorationImplementInCSRINTEL =
233253
static_cast<Decoration>(IDecImplementInCSRINTEL);
234254
constexpr Decoration DecorationArgumentAttributeINTEL =
235255
static_cast<Decoration>(IDecArgumentAttributeINTEL);
256+
constexpr Decoration DecorationCacheControlLoadINTEL =
257+
static_cast<Decoration>(IDecCacheControlLoadINTEL);
258+
constexpr Decoration DecorationCacheControlStoreINTEL =
259+
static_cast<Decoration>(IDecCacheControlStoreINTEL);
236260

237261
constexpr Capability CapabilityFastCompositeINTEL =
238262
static_cast<Capability>(ICapFastCompositeINTEL);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-SPIRV
3+
; RUN: llvm-spirv --spirv-ext=+SPV_INTEL_cache_controls %t.bc -o %t.spv
4+
; RUN: llvm-spirv -r %t.spv --spirv-target-env=SPV-IR -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-LLVM
5+
6+
; CHECK-SPIRV-DAG: Load {{[0-9]+}} {{[0-9]+}} [[LoadPtr:[0-9]+]]
7+
; CHECK-SPIRV-DAG: Store [[StorePtr:[0-9]+]]
8+
9+
; CHECK-SPIRV-DAG: Decorate [[LoadPtr]] CacheControlLoadINTEL 0 1
10+
; CHECK-SPIRV-DAG: Decorate [[LoadPtr]] CacheControlLoadINTEL 1 1
11+
; CHECK-SPIRV-DAG: Decorate [[StorePtr]] CacheControlStoreINTEL 0 1
12+
; CHECK-SPIRV-DAG: Decorate [[StorePtr]] CacheControlStoreINTEL 1 2
13+
14+
; CHECK-LLVM: %arrayidx = getelementptr inbounds i32, ptr addrspace(1) %buffer, i64 1, !spirv.Decorations [[LoadMD:![0-9]+]]
15+
; CHECK-LLVM: load i32, ptr addrspace(1) %arrayidx, align 4
16+
17+
; CHECK-LLVM: %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %buffer, i64 0, !spirv.Decorations [[StoreMD:![0-9]+]]
18+
; CHECK-LLVM: store i32 %0, ptr addrspace(1) %arrayidx1, align 4
19+
20+
; CHECK-LLVM: [[LoadMD]] = !{[[CC0:![0-9]+]], [[CC1:![0-9]+]]}
21+
; CHECK-LLVM: [[CC0]] = !{i32 6442, i32 0, i32 1}
22+
; CHECK-LLVM: [[CC1]] = !{i32 6442, i32 1, i32 1}
23+
24+
; CHECK-LLVM: [[StoreMD]] = !{[[CC2:![0-9]+]], [[CC3:![0-9]+]]}
25+
; CHECK-LLVM: [[CC2]] = !{i32 6443, i32 0, i32 1}
26+
; CHECK-LLVM: [[CC3]] = !{i32 6443, i32 1, i32 2}
27+
28+
target triple = "spir64-unknown-unknown"
29+
30+
define spir_kernel void @test(ptr addrspace(1) %buffer) {
31+
entry:
32+
%arrayidx = getelementptr inbounds i32, ptr addrspace(1) %buffer, i64 1, !spirv.Decorations !3
33+
%0 = load i32, ptr addrspace(1) %arrayidx, align 4
34+
%arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %buffer, i64 0, !spirv.Decorations !6
35+
store i32 %0, ptr addrspace(1) %arrayidx1, align 4
36+
ret void
37+
}
38+
39+
!spirv.MemoryModel = !{!0}
40+
!spirv.Source = !{!1}
41+
!opencl.spir.version = !{!2}
42+
!opencl.ocl.version = !{!2}
43+
44+
!0 = !{i32 2, i32 2}
45+
!1 = !{i32 3, i32 102000}
46+
!2 = !{i32 1, i32 2}
47+
!3 = !{!4, !5}
48+
!4 = !{i32 6442, i32 0, i32 1} ; {CacheControlLoadINTEL, CacheLevel=0, Cached}
49+
!5 = !{i32 6442, i32 1, i32 1} ; {CacheControlLoadINTEL, CacheLevel=1, Cached}
50+
!6 = !{!7, !8}
51+
!7 = !{i32 6443, i32 0, i32 1} ; {CacheControlStoreINTEL, CacheLevel=0, WriteThrough}
52+
!8 = !{i32 6443, i32 1, i32 2} ; {CacheControlStoreINTEL, CacheLevel=1, WriteBack}

0 commit comments

Comments
 (0)