diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc index c33e2c1cbe..7e6b8a7a55 100644 --- a/include/LLVMSPIRVExtensions.inc +++ b/include/LLVMSPIRVExtensions.inc @@ -14,3 +14,4 @@ EXT(SPV_INTEL_fpga_reg) EXT(SPV_INTEL_blocking_pipes) EXT(SPV_INTEL_function_pointers) EXT(SPV_INTEL_kernel_attributes) +EXT(SPV_INTEL_io_pipes) diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index 00a9479e50..9c58be6c6a 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -3046,8 +3046,17 @@ void SPIRVToLLVM::transIntelFPGADecorations(SPIRVValue *BV, Value *V) { SmallString<256> AnnotStr; generateIntelFPGAAnnotation(BV, AnnotStr); - if (AnnotStr.empty()) + if (AnnotStr.empty()) { + // Check if IO pipe decoration is applied to the global + SPIRVWord ID; + if (BV->hasDecorate(DecorationIOPipeStorageINTEL, 0, &ID)) { + auto Literals = BV->getDecorationLiterals(DecorationIOPipeStorageINTEL); + assert(Literals.size() == 1 && + "IO PipeStorage decoration shall have 1 ID literal"); + GV->setMetadata("io_pipe_id", getMDNodeStringIntVec(Context, Literals)); + } return; + } Constant *StrConstant = ConstantDataArray::getString(*Context, StringRef(AnnotStr)); diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index b45907d2d5..58629a2494 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp @@ -1902,10 +1902,23 @@ void LLVMToSPIRV::transGlobalAnnotation(GlobalVariable *V) { } } +void LLVMToSPIRV::transGlobalIOPipeStorage(GlobalVariable *V, MDNode *IO) { + SPIRVDBG(dbgs() << "[transGlobalIOPipeStorage] " << *V << '\n'); + SPIRVValue *SV = transValue(V, nullptr); + assert(SV && "Failed to process OCL PipeStorage object"); + if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_io_pipes)) { + BM->addCapability(CapabilityIOPipeINTEL); + unsigned ID = getMDOperandAsInt(IO, 0); + SV->addDecorate(DecorationIOPipeStorageINTEL, ID); + } +} + bool LLVMToSPIRV::transGlobalVariables() { for (auto I = M->global_begin(), E = M->global_end(); I != E; ++I) { if ((*I).getName() == "llvm.global.annotations") transGlobalAnnotation(&(*I)); + else if (MDNode *IO = ((*I).getMetadata("io_pipe_id"))) + transGlobalIOPipeStorage(&(*I), IO); else if (!transValue(&(*I), nullptr)) return false; } diff --git a/lib/SPIRV/SPIRVWriter.h b/lib/SPIRV/SPIRVWriter.h index a901052897..ae2d70da90 100644 --- a/lib/SPIRV/SPIRVWriter.h +++ b/lib/SPIRV/SPIRVWriter.h @@ -113,6 +113,7 @@ class LLVMToSPIRV : public ModulePass { void transGlobalAnnotation(GlobalVariable *V); SPIRVValue *transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB, bool CreateForward = true); + void transGlobalIOPipeStorage(GlobalVariable *V, MDNode *IO); typedef DenseMap LLVMToSPIRVTypeMap; typedef DenseMap LLVMToSPIRVValueMap; diff --git a/lib/SPIRV/libSPIRV/SPIRVDecorate.h b/lib/SPIRV/libSPIRV/SPIRVDecorate.h index ea816ba62d..e976c51dbb 100644 --- a/lib/SPIRV/libSPIRV/SPIRVDecorate.h +++ b/lib/SPIRV/libSPIRV/SPIRVDecorate.h @@ -156,6 +156,8 @@ class SPIRVDecorate : public SPIRVDecorateGeneric { return getSet(ExtensionID::SPV_INTEL_fpga_memory_attributes); case DecorationReferencedIndirectlyINTEL: return getSet(ExtensionID::SPV_INTEL_function_pointers); + case DecorationIOPipeStorageINTEL: + return getSet(ExtensionID::SPV_INTEL_io_pipes); default: return SPIRVExtSet(); } @@ -251,6 +253,8 @@ class SPIRVMemberDecorate : public SPIRVDecorateGeneric { case DecorationMergeINTEL: case DecorationBankBitsINTEL: return getSet(ExtensionID::SPV_INTEL_fpga_memory_attributes); + case DecorationIOPipeStorageINTEL: + return getSet(ExtensionID::SPV_INTEL_io_pipes); default: return SPIRVExtSet(); } diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h index 0fe6cf7ccd..33308a1df8 100644 --- a/lib/SPIRV/libSPIRV/SPIRVEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h @@ -365,6 +365,7 @@ template <> inline void SPIRVMap::init() { ADD_VEC_INIT(DecorationBankBitsINTEL, {CapabilityFPGAMemoryAttributesINTEL}); ADD_VEC_INIT(DecorationReferencedIndirectlyINTEL, {CapabilityIndirectReferencesINTEL}); + ADD_VEC_INIT(DecorationIOPipeStorageINTEL, {CapabilityIOPipeINTEL}); } template <> inline void SPIRVMap::init() { diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index b67b47ba96..1e3c6f09b9 100644 --- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -348,6 +348,7 @@ template <> inline void SPIRVMap::init() { add(DecorationMergeINTEL, "MergeINTEL"); add(DecorationBankBitsINTEL, "BankBitsINTEL"); add(DecorationReferencedIndirectlyINTEL, "ReferencedIndirectlyINTEL"); + add(DecorationIOPipeStorageINTEL, "IOPipeStorageINTEL"); } SPIRV_DEF_NAMEMAP(Decoration, SPIRVDecorationNameMap) @@ -502,6 +503,7 @@ template <> inline void SPIRVMap::init() { add(CapabilityIndirectReferencesINTEL, "IndirectReferencesINTEL"); add(CapabilityKernelAttributesINTEL, "KernelAttributesINTEL"); add(CapabilityFPGAKernelAttributesINTEL, "FPGAKernelAttributesINTEL"); + add(CapabilityIOPipeINTEL, "IOPipeINTEL"); } SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) diff --git a/lib/SPIRV/libSPIRV/spirv.hpp b/lib/SPIRV/libSPIRV/spirv.hpp index 9065221438..2a59f2cd90 100644 --- a/lib/SPIRV/libSPIRV/spirv.hpp +++ b/lib/SPIRV/libSPIRV/spirv.hpp @@ -405,6 +405,7 @@ enum Decoration { DecorationSimpleDualPortINTEL = 5833, DecorationMergeINTEL = 5834, DecorationBankBitsINTEL = 5835, + DecorationIOPipeStorageINTEL = 5944, DecorationMax = 0x7fffffff, }; @@ -690,6 +691,7 @@ enum Capability { CapabilityFPGARegINTEL = 5948, CapabilityKernelAttributesINTEL= 5892, CapabilityFPGAKernelAttributesINTEL= 5897, + CapabilityIOPipeINTEL = 5943, CapabilityMax = 0x7fffffff, }; diff --git a/test/PipeStorageIOINTEL.ll b/test/PipeStorageIOINTEL.ll new file mode 100644 index 0000000000..0d2caa9753 --- /dev/null +++ b/test/PipeStorageIOINTEL.ll @@ -0,0 +1,66 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_io_pipes -o %t.spv +; RUN: llvm-spirv %t.spv -to-text -o %t.spt +; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV + +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + +; RUN: llvm-spirv -spirv-text -r %t.spt -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + +; CHECK-LLVM: %spirv.ConstantPipeStorage = type { i32, i32, i32 } +; CHECK-LLVM: %"[[CL_PIPE_STORAGE_NAME:[^"]+]]" = type { %spirv.PipeStorage addrspace(1)* } +; CHECK-LLVM: %spirv.PipeStorage = type opaque +; CHECK-LLVM: [[CREATOR_NAME:[^ ]+]] = linkonce_odr addrspace(1) global %spirv.ConstantPipeStorage { i32 16, i32 16, i32 1 }, align 4 +; CHECK-LLVM: @mygpipe = addrspace(1) global %"[[CL_PIPE_STORAGE_NAME]]" { %spirv.PipeStorage addrspace(1)* bitcast (%spirv.ConstantPipeStorage addrspace(1)* [[CREATOR_NAME]] to %spirv.PipeStorage addrspace(1)*) }, align 4, !io_pipe_id ![[IO_MD:[0-9]+]] +; CHECK-LLVM: ![[IO_MD]] = !{i32 1} + +; CHECK-SPIRV: 2 Capability PipeStorage +; CHECK-SPIRV: 2 Capability IOPipeINTEL +; CHECK-SPIRV: 6 Extension "SPV_INTEL_io_pipes" + +; CHECK-SPIRV: 4 Name [[MYPIPE_ID:[0-9]+]] "mygpipe" +; CHECK-SPIRV: 4 Decorate [[MYPIPE_ID]] IOPipeStorageINTEL 1 + +; CHECK-SPIRV: 2 TypePipeStorage [[PIPE_STORAGE_ID:[0-9]+]] +; CHECK-SPIRV-NEXT: 2 TypePipeStorage [[PIPE_STORAGE_ID_2:[0-9]+]] +; CHECK-SPIRV: 3 TypeStruct [[CL_PIPE_STORAGE_ID:[0-9]+]] [[PIPE_STORAGE_ID_2]] +; CHECK-SPIRV: 4 TypePointer [[CL_PIPE_STORAGE_PTR_ID:[0-9]+]] 5 [[CL_PIPE_STORAGE_ID]] + +; CHECK-SPIRV: 6 ConstantPipeStorage [[PIPE_STORAGE_ID]] [[CPS_ID:[0-9]+]] 16 16 1 +; CHECK-SPIRV: 4 ConstantComposite [[CL_PIPE_STORAGE_ID]] [[COMPOSITE_ID:[0-9]+]] [[CPS_ID]] +; CHECK-SPIRV: 5 Variable [[CL_PIPE_STORAGE_PTR_ID]] [[MYPIPE_ID]] 5 [[COMPOSITE_ID]] + +target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +target triple = "spir-unknown-unknown" + +%spirv.ConstantPipeStorage = type { i32, i32, i32 } +%"class.cl::pipe_storage" = type { %spirv.PipeStorage addrspace(1)* } +%spirv.PipeStorage = type opaque + +@_ZN2cl9__details29OpConstantPipeStorage_CreatorILi16ELi16ELi1EE5valueE = linkonce_odr addrspace(1) global %spirv.ConstantPipeStorage { i32 16, i32 16, i32 1 }, align 4 +@mygpipe = addrspace(1) global %"class.cl::pipe_storage" { %spirv.PipeStorage addrspace(1)* bitcast (%spirv.ConstantPipeStorage addrspace(1)* @_ZN2cl9__details29OpConstantPipeStorage_CreatorILi16ELi16ELi1EE5valueE to %spirv.PipeStorage addrspace(1)*) }, align 4, !io_pipe_id !5 + +; Function Attrs: nounwind +define spir_kernel void @worker() { +entry: + ret void +} + +!opencl.enable.FP_CONTRACT = !{} +!opencl.spir.version = !{!0} +!opencl.ocl.version = !{!1} +!opencl.used.extensions = !{!2} +!opencl.used.optional.core.features = !{!2} +!opencl.compiler.options = !{!2} +!llvm.ident = !{!3} +!spirv.Source = !{!4} +!spirv.String = !{} + +!0 = !{i32 1, i32 2} +!1 = !{i32 2, i32 2} +!2 = !{} +!3 = !{!"clang version 3.6.1 "} +!4 = !{i32 4, i32 202000} +!5 = !{i32 1}