Skip to content

Commit f71cec5

Browse files
MrSidimsAlexander Batashev
authored and
Alexander Batashev
committed
Add support for SPV_INTEL_fpga_buffer_location extension
This extension adds a function parameter decoration that is useful for FPGA targets. This decoration indicates that a particular global memory pointer can only access a particular physical memory location. Knowing this information at compile time can allow FPGA compilers to generate load store units of lower area for accesses done through such a pointer. Specification: intel#2084 Signed-off-by: Dmitry Sidorov <[email protected]>
1 parent 041a03d commit f71cec5

File tree

8 files changed

+118
-0
lines changed

8 files changed

+118
-0
lines changed

llvm-spirv/include/LLVMSPIRVExtensions.inc

+1
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ EXT(SPV_INTEL_optimization_hints)
2323
EXT(SPV_INTEL_float_controls2)
2424
EXT(SPV_INTEL_vector_compute)
2525
EXT(SPV_INTEL_usm_storage_classes)
26+
EXT(SPV_INTEL_fpga_buffer_location)

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,27 @@ static void addOCLKernelArgumentMetadata(
168168
Fn->setMetadata(MDName, MDNode::get(*Context, ValueVec));
169169
}
170170

171+
static void addBufferLocationMetadata(
172+
LLVMContext *Context, SPIRVFunction *BF, llvm::Function *Fn,
173+
std::function<Metadata *(SPIRVFunctionParameter *)> Func) {
174+
std::vector<Metadata *> ValueVec;
175+
bool DecorationFound = false;
176+
BF->foreachArgument([&](SPIRVFunctionParameter *Arg) {
177+
if (Arg->getType()->isTypePointer() &&
178+
Arg->hasDecorate(DecorationBufferLocationINTEL)) {
179+
DecorationFound = true;
180+
ValueVec.push_back(Func(Arg));
181+
} else {
182+
llvm::Metadata *DefaultNode = ConstantAsMetadata::get(
183+
ConstantInt::get(Type::getInt32Ty(*Context), -1));
184+
ValueVec.push_back(DefaultNode);
185+
}
186+
});
187+
if (DecorationFound)
188+
Fn->setMetadata("kernel_arg_buffer_location",
189+
MDNode::get(*Context, ValueVec));
190+
}
191+
171192
Value *SPIRVToLLVM::getTranslatedValue(SPIRVValue *BV) {
172193
auto Loc = ValueMap.find(BV);
173194
if (Loc != ValueMap.end())
@@ -3479,6 +3500,15 @@ bool SPIRVToLLVM::transOCLMetadata(SPIRVFunction *BF) {
34793500
Arg->getName());
34803501
});
34813502
}
3503+
// Generate metadata for kernel_arg_buffer_location
3504+
addBufferLocationMetadata(Context, BF, F, [=](SPIRVFunctionParameter *Arg) {
3505+
auto Literals = Arg->getDecorationLiterals(DecorationBufferLocationINTEL);
3506+
assert(Literals.size() == 1 &&
3507+
"BufferLocationINTEL decoration shall have 1 ID literal");
3508+
3509+
return ConstantAsMetadata::get(
3510+
ConstantInt::get(Type::getInt32Ty(*Context), Literals[0]));
3511+
});
34823512
return true;
34833513
}
34843514

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,13 @@ SPIRVFunction *LLVMToSPIRV::transFunctionDecl(Function *F) {
527527
BM->addEntryPoint(ExecutionModelKernel, BF->getId());
528528
else if (F->getLinkage() != GlobalValue::InternalLinkage)
529529
BF->setLinkageType(transLinkageType(F));
530+
531+
// Translate OpenCL/SYCL buffer_location metadata if it's attached to the
532+
// translated function declaration
533+
MDNode *BufferLocation = nullptr;
534+
if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fpga_buffer_location))
535+
BufferLocation = ((*F).getMetadata("kernel_arg_buffer_location"));
536+
530537
auto Attrs = F->getAttributes();
531538

532539
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
@@ -552,6 +559,15 @@ SPIRVFunction *LLVMToSPIRV::transFunctionDecl(Function *F) {
552559
BA->addDecorate(DecorationMaxByteOffset,
553560
Attrs.getAttribute(ArgNo + 1, Attribute::Dereferenceable)
554561
.getDereferenceableBytes());
562+
if (BufferLocation && I->getType()->isPointerTy()) {
563+
// Order of integer numbers in MD node follows the order of function
564+
// parameters on which we shall attach the appropriate decoration. Add
565+
// decoration only if MD value is not negative.
566+
BM->addCapability(CapabilityFPGABufferLocationINTEL);
567+
int LocID = getMDOperandAsInt(BufferLocation, ArgNo);
568+
if (LocID >= 0)
569+
BA->addDecorate(DecorationBufferLocationINTEL, LocID);
570+
}
555571
}
556572
if (Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::ZExt))
557573
BF->addDecorate(DecorationFuncParamAttr, FunctionParameterAttributeZext);

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVDecorate.h

+4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ class SPIRVDecorate : public SPIRVDecorateGeneric {
164164
return getSet(ExtensionID::SPV_INTEL_function_pointers);
165165
case DecorationIOPipeStorageINTEL:
166166
return getSet(ExtensionID::SPV_INTEL_io_pipes);
167+
case DecorationBufferLocationINTEL:
168+
return getSet(ExtensionID::SPV_INTEL_fpga_buffer_location);
167169
default:
168170
return SPIRVExtSet();
169171
}
@@ -267,6 +269,8 @@ class SPIRVMemberDecorate : public SPIRVDecorateGeneric {
267269
return getSet(ExtensionID::SPV_INTEL_fpga_memory_accesses);
268270
case DecorationIOPipeStorageINTEL:
269271
return getSet(ExtensionID::SPV_INTEL_io_pipes);
272+
case DecorationBufferLocationINTEL:
273+
return getSet(ExtensionID::SPV_INTEL_fpga_buffer_location);
270274
default:
271275
return SPIRVExtSet();
272276
}

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h

+2
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,8 @@ template <> inline void SPIRVMap<Decoration, SPIRVCapVec>::init() {
402402
ADD_VEC_INIT(DecorationDontStaticallyCoalesceINTEL,
403403
{CapabilityFPGAMemoryAccessesINTEL});
404404
ADD_VEC_INIT(DecorationPrefetchINTEL, {CapabilityFPGAMemoryAccessesINTEL});
405+
ADD_VEC_INIT(DecorationBufferLocationINTEL,
406+
{CapabilityFPGABufferLocationINTEL});
405407
}
406408

407409
template <> inline void SPIRVMap<BuiltIn, SPIRVCapVec>::init() {

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

+2
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ template <> inline void SPIRVMap<Decoration, std::string>::init() {
376376
add(DecorationGlobalVariableOffsetINTEL, "GlobalVariableOffsetINTEL");
377377
add(DecorationFuncParamIOKind, "FuncParamIOKind");
378378
add(DecorationSIMTCallINTEL, "SIMTCallINTEL");
379+
add(DecorationBufferLocationINTEL, "BufferLocationINTEL");
379380
}
380381
SPIRV_DEF_NAMEMAP(Decoration, SPIRVDecorationNameMap)
381382

@@ -560,6 +561,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
560561
"GroupNonUniformShuffleRelative");
561562
add(CapabilityGroupNonUniformClustered, "GroupNonUniformClustered");
562563
add(CapabilityUSMStorageClassesINTEL, "USMStorageClassesINTEL");
564+
add(CapabilityFPGABufferLocationINTEL, "FPGABufferLocationINTEL");
563565
}
564566
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)
565567

llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ enum Decoration {
508508
DecorationCacheSizeINTEL = 5900,
509509
DecorationDontStaticallyCoalesceINTEL = 5901,
510510
DecorationPrefetchINTEL = 5902,
511+
DecorationBufferLocationINTEL = 5921,
511512
DecorationIOPipeStorageINTEL = 5944,
512513
DecorationMax = 0x7fffffff,
513514
};
@@ -962,6 +963,7 @@ enum Capability {
962963
CapabilityFPGARegINTEL = 5948,
963964
CapabilityKernelAttributesINTEL = 5892,
964965
CapabilityFPGAKernelAttributesINTEL = 5897,
966+
CapabilityFPGABufferLocationINTEL = 5920,
965967
CapabilityUSMStorageClassesINTEL = 5935,
966968
CapabilityFPGAMemoryAccessesINTEL = 5898,
967969
CapabilityIOPipeINTEL = 5943,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_fpga_buffer_location -o %t.spv
3+
; RUN: llvm-spirv %t.spv -to-text -o %t.spt
4+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
5+
6+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
7+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
8+
9+
; RUN: llvm-spirv -spirv-text -r %t.spt -o %t.rev.bc
10+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
11+
12+
; CHECK-SPIRV: 2 Capability FPGABufferLocationINTEL
13+
; CHECK-SPIRV: 9 Extension "SPV_INTEL_fpga_buffer_location"
14+
; CHECK-SPIRV: 3 Name [[ARGA:[0-9]+]] "a"
15+
; CHECK-SPIRV: 3 Name [[ARGB:[0-9]+]] "b"
16+
; CHECK-SPIRV: 3 Name [[ARGC:[0-9]+]] "c"
17+
; CHECK-SPIRV: 3 Name [[ARGD:[0-9]+]] "d"
18+
; CHECK-SPIRV: 3 Name [[ARGE:[0-9]+]] "e"
19+
; CHECK-SPIRV-NOT: 4 Decorate [[ARGC]] BufferLocationINTEL -1
20+
; CHECK-SPIRV-NOT: 4 Decorate [[ARGC]] BufferLocationINTEL -1
21+
; CHECK-SPIRV: 4 Decorate [[ARGA]] BufferLocationINTEL 1
22+
; CHECK-SPIRV: 4 Decorate [[ARGB]] BufferLocationINTEL 2
23+
; CHECK-SPIRV-NOT: 4 Decorate [[ARGD]] BufferLocationINTEL -1
24+
; CHECK-SPIRV-NOT: 4 Decorate [[ARGE]] BufferLocationINTEL 3
25+
26+
; CHECK-SPIRV: 5 Function
27+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGA]]
28+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGB]]
29+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGC]]
30+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGD]]
31+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGE]]
32+
33+
; CHECK-LLVM: define spir_kernel void @test{{.*}} !kernel_arg_buffer_location ![[BUFLOC_MD:[0-9]+]] {{.*}}
34+
; CHECK-LLVM: ![[BUFLOC_MD]] = !{i32 1, i32 2, i32 -1, i32 -1, i32 -1}
35+
36+
; ModuleID = 'buffer_location.cl'
37+
source_filename = "buffer_location.cl"
38+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
39+
target triple = "spir64-unknown-unknown"
40+
41+
; Function Attrs: norecurse nounwind readnone
42+
define spir_kernel void @test(i32 addrspace(1)* %a, float addrspace(1)* %b, i32 addrspace(1)* %c, i32 %d, i32 %e) local_unnamed_addr !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !5 !kernel_arg_buffer_location !6 {
43+
entry:
44+
ret void
45+
}
46+
47+
!opencl.enable.FP_CONTRACT = !{}
48+
!opencl.ocl.version = !{!0}
49+
!opencl.spir.version = !{!0}
50+
!opencl.used.extensions = !{!1}
51+
!opencl.used.optional.core.features = !{!1}
52+
!opencl.compiler.options = !{!1}
53+
!llvm.ident = !{!2}
54+
55+
!0 = !{i32 2, i32 0}
56+
!1 = !{}
57+
!2 = !{!""}
58+
!3 = !{i32 1, i32 1, i32 1}
59+
!4 = !{!"none", !"none", !"none"}
60+
!5 = !{!"int*", !"float*", !"int*"}
61+
!6 = !{i32 1, i32 2, i32 -1, i32 -1, i32 3}

0 commit comments

Comments
 (0)