Skip to content

Commit 093352b

Browse files
MrSidimssys-ce-bb
authored andcommitted
Add support for multiple Intel cache controls on a single argument (#2599)
In this case zero GEP will be created a single time, all the decorations will be attached to it. Signed-off-by: Sidorov, Dmitry <[email protected]> Original commit: KhronosGroup/SPIRV-LLVM-Translator@9aa3c9c12f51775
1 parent 09dea92 commit 093352b

File tree

3 files changed

+93
-7
lines changed

3 files changed

+93
-7
lines changed

llvm-spirv/lib/SPIRV/SPIRVRegularizeLLVM.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ void prepareCacheControlsTranslation(Metadata *MD, Instruction *Inst) {
569569
return;
570570
auto *ArgDecoMD = dyn_cast<MDNode>(MD);
571571
assert(ArgDecoMD && "Decoration list must be a metadata node");
572+
std::vector<Instruction *> CreatedGeps;
572573
for (unsigned I = 0, E = ArgDecoMD->getNumOperands(); I != E; ++I) {
573574
auto *DecoMD = dyn_cast<MDNode>(ArgDecoMD->getOperand(I));
574575
if (!DecoMD) {
@@ -597,19 +598,36 @@ void prepareCacheControlsTranslation(Metadata *MD, Instruction *Inst) {
597598

598599
// Create dummy GEP for SSA copy of the pointer operand. Lets do our best
599600
// to guess pointee type here, but if we won't - just pointer is also fine,
600-
// if necessary TypeScavenger will adjust types and create bitcasts.
601+
// if necessary TypeScavenger will adjust types and create bitcasts. If
602+
// memory instruction operand is already created zero GEP - create nothing
603+
// and use the old GEP.
604+
SmallVector<Metadata *, 4> MDs;
605+
std::vector<Metadata *> OPs = {KindMD, LevelMD, ControlMD};
606+
if (auto *const GEP = dyn_cast<GetElementPtrInst>(PtrInstOp)) {
607+
if (GEP->hasAllZeroIndices() &&
608+
(std::find(CreatedGeps.begin(), CreatedGeps.end(), GEP) !=
609+
std::end(CreatedGeps))) {
610+
MDs.push_back(MDNode::get(Inst->getContext(), OPs));
611+
// If the existing GEP has SPIRV_MD_DECORATIONS metadata - copy it
612+
if (auto *OldMD = GEP->getMetadata(SPIRV_MD_DECORATIONS))
613+
for (unsigned I = 0, E = OldMD->getNumOperands(); I != E; ++I)
614+
if (auto *DecoMD = dyn_cast<MDNode>(OldMD->getOperand(I)))
615+
MDs.push_back(DecoMD);
616+
MDNode *MDList = MDNode::get(Inst->getContext(), MDs);
617+
GEP->setMetadata(SPIRV_MD_DECORATIONS, MDList);
618+
return;
619+
}
620+
}
601621
IRBuilder Builder(Inst);
602-
Type *GEPTy = PtrInstOp->getType();
622+
Type *GEPTy = Builder.getInt8Ty();
603623
if (auto *LI = dyn_cast<LoadInst>(Inst))
604624
GEPTy = LI->getType();
605625
else if (auto *SI = dyn_cast<StoreInst>(Inst))
606626
GEPTy = SI->getValueOperand()->getType();
607627
auto *GEP =
608628
cast<Instruction>(Builder.CreateConstGEP1_32(GEPTy, PtrInstOp, 0));
629+
CreatedGeps.push_back(GEP);
609630
Inst->setOperand(TargetArgNo, GEP);
610-
611-
SmallVector<Metadata *, 4> MDs;
612-
std::vector<Metadata *> OPs = {KindMD, LevelMD, ControlMD};
613631
MDs.push_back(MDNode::get(Inst->getContext(), OPs));
614632
MDNode *MDList = MDNode::get(Inst->getContext(), MDs);
615633
GEP->setMetadata(SPIRV_MD_DECORATIONS, MDList);

llvm-spirv/test/extensions/INTEL/SPV_INTEL_cache_controls/call_inst_arg_dec.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
; CHECK-SPIRV: PtrAccessChain [[#]] [[#GEP2]] [[#]] [[#Zero]]
1212
; CHECK-SPIRV: FunctionCall [[#]] [[#]] [[#]] [[#GEP1]] [[#GEP2]]
1313

14-
; CHECK-LLVM: %[[#GEP1:]] = getelementptr ptr addrspace(1), ptr addrspace(1) %{{.*}}, i32 0, !spirv.Decorations ![[#Cache1:]]
15-
; CHECK-LLVM: %[[#GEP2:]] = getelementptr ptr addrspace(1), ptr addrspace(1) %{{.*}}, i32 0, !spirv.Decorations ![[#Cache2:]]
14+
; CHECK-LLVM: %[[#GEP1:]] = getelementptr i8, ptr addrspace(1) %{{.*}}, i32 0, !spirv.Decorations ![[#Cache1:]]
15+
; CHECK-LLVM: %[[#GEP2:]] = getelementptr i8, ptr addrspace(1) %{{.*}}, i32 0, !spirv.Decorations ![[#Cache2:]]
1616
; CHECK-LLVM: call spir_func void @foo(ptr addrspace(1) %[[#GEP1]], ptr addrspace(1) %[[#GEP2]])
1717
; CHECK-LLVM: ![[#Cache1]] = !{![[#LoadCache:]]}
1818
; CHECK-LLVM: ![[#LoadCache]] = !{i32 6442, i32 0, i32 1}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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: Name [[#Func:]] "test"
7+
; CHECK-SPIRV-DAG: Name [[#FuncGEP:]] "test_gep"
8+
; CHECK-SPIRV-DAG: TypeInt [[#Int32:]] 32 0
9+
; CHECK-SPIRV-DAG: Constant [[#Int32]] [[#Zero:]] 0
10+
; CHECK-SPIRV-DAG: Decorate [[#GEP1:]] CacheControlLoadINTEL 1 1
11+
; CHECK-SPIRV-DAG: Decorate [[#GEP1]] CacheControlLoadINTEL 0 3
12+
; CHECK-SPIRV-DAG: Decorate [[#GEP2:]] CacheControlLoadINTEL 1 1
13+
; CHECK-SPIRV-DAG: Decorate [[#GEP2]] CacheControlLoadINTEL 0 3
14+
15+
; CHECK-SPIRV: Function [[#]] [[#Func]]
16+
; CHECK-SPIRV: FunctionParameter [[#]] [[#Buffer:]]
17+
; CHECK-SPIRV: PtrAccessChain [[#]] [[#GEP1]] [[#Buffer]] [[#Zero]]
18+
; CHECK-SPIRV: FunctionCall [[#]] [[#]] [[#]] [[#GEP1]]
19+
20+
; CHECK-SPIRV: Function [[#]] [[#FuncGEP]]
21+
; CHECK-SPIRV: FunctionParameter [[#]] [[#Buffer:]]
22+
; CHECK-SPIRV: PtrAccessChain [[#]] [[#GEP3:]] [[#Buffer]] [[#Zero]]
23+
; CHECK-SPIRV: Bitcast [[#]] [[#BitCast:]] [[#GEP3]]
24+
; CHECK-SPIRV: PtrAccessChain [[#]] [[#GEP2]] [[#BitCast:]] [[#Zero]]
25+
; CHECK-SPIRV: FunctionCall [[#]] [[#]] [[#]] [[#GEP2]]
26+
27+
; CHECK-LLVM: define spir_kernel void @test(ptr addrspace(1) %[[Param1:[a-z0-9_.]+]])
28+
; CHECK-LLVM: %[[#GEP:]] = getelementptr i8, ptr addrspace(1) %[[Param1]], i32 0, !spirv.Decorations ![[#MD:]]
29+
; CHECK-LLVM: call spir_func void @foo(ptr addrspace(1) %[[#GEP:]])
30+
31+
; CHECK-LLVM: define spir_kernel void @test_gep(ptr addrspace(1) %[[Param2:[a-z0-9_.]+]])
32+
; CHECK-LLVM: %[[#GEP1:]] = getelementptr ptr addrspace(1), ptr addrspace(1) %[[Param2]], i32 0
33+
; CHECK-LLVM: %[[#BitCast:]] = bitcast ptr addrspace(1) %[[#GEP1]] to ptr addrspace(1)
34+
; CHECK-LLVM: %[[#GEP2:]] = getelementptr i8, ptr addrspace(1) %[[#BitCast]], i32 0, !spirv.Decorations ![[#MD]]
35+
; CHECK-LLVM: call spir_func void @foo(ptr addrspace(1) %[[#GEP2:]])
36+
37+
; CHECK-LLVM: ![[#MD]] = !{![[#Dec1:]], ![[#Dec2:]]}
38+
; CHECK-LLVM: ![[#Dec1]] = !{i32 6442, i32 1, i32 1}
39+
; CHECK-LLVM: ![[#Dec2]] = !{i32 6442, i32 0, i32 3}
40+
41+
target triple = "spir64-unknown-unknown"
42+
43+
define spir_kernel void @test(ptr addrspace(1) %buffer1) {
44+
entry:
45+
call void @foo(ptr addrspace(1) %buffer1), !spirv.DecorationCacheControlINTEL !3
46+
ret void
47+
}
48+
49+
define spir_kernel void @test_gep(ptr addrspace(1) %buffer1) {
50+
entry:
51+
%0 = getelementptr ptr addrspace(1), ptr addrspace(1) %buffer1, i32 0
52+
call void @foo(ptr addrspace(1) %0), !spirv.DecorationCacheControlINTEL !3
53+
ret void
54+
}
55+
56+
declare void @foo(ptr addrspace(1))
57+
58+
!spirv.MemoryModel = !{!0}
59+
!spirv.Source = !{!1}
60+
!opencl.spir.version = !{!2}
61+
!opencl.ocl.version = !{!2}
62+
63+
!0 = !{i32 2, i32 2}
64+
!1 = !{i32 3, i32 102000}
65+
!2 = !{i32 1, i32 2}
66+
!3 = !{!4, !5}
67+
!4 = !{i32 6442, i32 0, i32 3, i32 0}
68+
!5 = !{i32 6442, i32 1, i32 1, i32 0}

0 commit comments

Comments
 (0)