Skip to content

Commit 643a320

Browse files
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 articular 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/llvm#2084 Signed-off-by: Dmitry Sidorov <[email protected]>
1 parent 2846475 commit 643a320

File tree

8 files changed

+103
-0
lines changed

8 files changed

+103
-0
lines changed

include/LLVMSPIRVExtensions.inc

+1
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ EXT(SPV_INTEL_optimization_hints)
2222
EXT(SPV_INTEL_float_controls2)
2323
EXT(SPV_INTEL_vector_compute)
2424
EXT(SPV_INTEL_usm_storage_classes)
25+
EXT(SPV_INTEL_fpga_buffer_location)

lib/SPIRV/SPIRVReader.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,20 @@ 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+
BF->foreachArgument([&](SPIRVFunctionParameter *Arg) {
176+
if (Arg->getType()->isTypePointer() &&
177+
Arg->hasDecorate(DecorationBufferLocationINTEL))
178+
ValueVec.push_back(Func(Arg));
179+
});
180+
if (ValueVec.size())
181+
Fn->setMetadata("kernel_arg_buffer_location",
182+
MDNode::get(*Context, ValueVec));
183+
}
184+
171185
Value *SPIRVToLLVM::getTranslatedValue(SPIRVValue *BV) {
172186
auto Loc = ValueMap.find(BV);
173187
if (Loc != ValueMap.end())
@@ -3443,6 +3457,15 @@ bool SPIRVToLLVM::transOCLMetadata(SPIRVFunction *BF) {
34433457
Arg->getName());
34443458
});
34453459
}
3460+
// Generate metadata for kernel_arg_buffer_location
3461+
addBufferLocationMetadata(Context, BF, F, [=](SPIRVFunctionParameter *Arg) {
3462+
auto Literals = Arg->getDecorationLiterals(DecorationBufferLocationINTEL);
3463+
assert(Literals.size() == 1 &&
3464+
"BufferLocationINTEL decoration shall have 1 ID literal");
3465+
3466+
return ConstantAsMetadata::get(
3467+
ConstantInt::get(Type::getInt32Ty(*Context), Literals[0]));
3468+
});
34463469
return true;
34473470
}
34483471

lib/SPIRV/SPIRVWriter.cpp

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

530538
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
@@ -550,6 +558,13 @@ SPIRVFunction *LLVMToSPIRV::transFunctionDecl(Function *F) {
550558
BA->addDecorate(DecorationMaxByteOffset,
551559
Attrs.getAttribute(ArgNo + 1, Attribute::Dereferenceable)
552560
.getDereferenceableBytes());
561+
if (BufferLocation) {
562+
// Order of integer numbers in MD node follows the order of function
563+
// parameters on which we shall attach the appropriate decoration
564+
BM->addCapability(CapabilityFPGABufferLocationINTEL);
565+
size_t LocID = getMDOperandAsInt(BufferLocation, ArgNo);
566+
BA->addDecorate(DecorationBufferLocationINTEL, LocID);
567+
}
553568
}
554569
if (Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::ZExt))
555570
BF->addDecorate(DecorationFuncParamAttr, FunctionParameterAttributeZext);

lib/SPIRV/libSPIRV/SPIRVDecorate.h

+4
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class SPIRVDecorate : public SPIRVDecorateGeneric {
159159
return getSet(ExtensionID::SPV_INTEL_function_pointers);
160160
case DecorationIOPipeStorageINTEL:
161161
return getSet(ExtensionID::SPV_INTEL_io_pipes);
162+
case DecorationBufferLocationINTEL:
163+
return getSet(ExtensionID::SPV_INTEL_fpga_buffer_location);
162164
default:
163165
return SPIRVExtSet();
164166
}
@@ -257,6 +259,8 @@ class SPIRVMemberDecorate : public SPIRVDecorateGeneric {
257259
return getSet(ExtensionID::SPV_INTEL_fpga_memory_attributes);
258260
case DecorationIOPipeStorageINTEL:
259261
return getSet(ExtensionID::SPV_INTEL_io_pipes);
262+
case DecorationBufferLocationINTEL:
263+
return getSet(ExtensionID::SPV_INTEL_fpga_buffer_location);
260264
default:
261265
return SPIRVExtSet();
262266
}

lib/SPIRV/libSPIRV/SPIRVEnum.h

+2
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,8 @@ template <> inline void SPIRVMap<Decoration, SPIRVCapVec>::init() {
393393
{CapabilityVectorComputeINTEL});
394394
ADD_VEC_INIT(DecorationFuncParamIOKind, {CapabilityVectorComputeINTEL});
395395
ADD_VEC_INIT(DecorationStackCallINTEL, {CapabilityVectorComputeINTEL});
396+
ADD_VEC_INIT(DecorationBufferLocationINTEL,
397+
{CapabilityFPGABufferLocationINTEL});
396398
}
397399

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

lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

+2
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ template <> inline void SPIRVMap<Decoration, std::string>::init() {
369369
add(DecorationVectorComputeVariableINTEL, "VectorComputeVariableINTEL");
370370
add(DecorationGlobalVariableOffsetINTEL, "GlobalVariableOffsetINTEL");
371371
add(DecorationFuncParamIOKind, "FuncParamIOKind");
372+
add(DecorationBufferLocationINTEL, "BufferLocationINTEL");
372373
}
373374
SPIRV_DEF_NAMEMAP(Decoration, SPIRVDecorationNameMap)
374375

@@ -552,6 +553,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
552553
"GroupNonUniformShuffleRelative");
553554
add(CapabilityGroupNonUniformClustered, "GroupNonUniformClustered");
554555
add(CapabilityUSMStorageClassesINTEL, "USMStorageClassesINTEL");
556+
add(CapabilityFPGABufferLocationINTEL, "FPGABufferLocationINTEL");
555557
}
556558
SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap)
557559

lib/SPIRV/libSPIRV/spirv.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ enum Decoration {
501501
DecorationMergeINTEL = 5834,
502502
DecorationBankBitsINTEL = 5835,
503503
DecorationForcePow2DepthINTEL = 5836,
504+
DecorationBufferLocationINTEL = 5921,
504505
DecorationIOPipeStorageINTEL = 5944,
505506
DecorationMax = 0x7fffffff,
506507
};
@@ -956,6 +957,7 @@ enum Capability {
956957
CapabilityKernelAttributesINTEL = 5892,
957958
CapabilityFPGAKernelAttributesINTEL = 5897,
958959
CapabilityUSMStorageClassesINTEL = 5935,
960+
CapabilityFPGABufferLocationINTEL = 5920,
959961
CapabilityIOPipeINTEL = 5943,
960962
CapabilityMax = 0x7fffffff,
961963
};
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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: 4 Decorate [[ARGC]] BufferLocationINTEL 0
18+
; CHECK-SPIRV: 4 Decorate [[ARGA]] BufferLocationINTEL 1
19+
; CHECK-SPIRV: 4 Decorate [[ARGB]] BufferLocationINTEL 2
20+
21+
; CHECK-SPIRV: 5 Function
22+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGA]]
23+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGB]]
24+
; CHECK-SPIRV: 3 FunctionParameter {{[0-9]+}} [[ARGC]]
25+
26+
; CHECK-LLVM: define spir_kernel void @test{{.*}} !kernel_arg_buffer_location ![[BUFLOC_MD:[0-9]+]] {{.*}}
27+
; CHECK-LLVM: ![[BUFLOC_MD]] = !{i32 1, i32 2, i32 0}
28+
29+
; ModuleID = 'buffer_location.cl'
30+
source_filename = "buffer_location.cl"
31+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
32+
target triple = "spir64-unknown-unknown"
33+
34+
; Function Attrs: norecurse nounwind readnone
35+
define spir_kernel void @test(i32 addrspace(1)* %a, float addrspace(1)* %b, i32 addrspace(1)* %c) 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 {
36+
entry:
37+
ret void
38+
}
39+
40+
!opencl.enable.FP_CONTRACT = !{}
41+
!opencl.ocl.version = !{!0}
42+
!opencl.spir.version = !{!0}
43+
!opencl.used.extensions = !{!1}
44+
!opencl.used.optional.core.features = !{!1}
45+
!opencl.compiler.options = !{!1}
46+
!llvm.ident = !{!2}
47+
48+
!0 = !{i32 2, i32 0}
49+
!1 = !{}
50+
!2 = !{!""}
51+
!3 = !{i32 1, i32 1, i32 1}
52+
!4 = !{!"none", !"none", !"none"}
53+
!5 = !{!"int*", !"float*", !"int*"}
54+
!6 = !{i32 1, i32 2, i32 0}

0 commit comments

Comments
 (0)