https://github.com/Keenuts created https://github.com/llvm/llvm-project/pull/116393
Draft PR to explore adding semantics & inline SPIR-V for builtins. This PR is an alternative to #115187 which does not requires a spec change as we keep the variables as `static [const]`. In addition, it tried to remain closer to DXIL by using a load/store builtin intrinsic instead of relying on an external global variable (IR level). ``` // RUN: %clang --driver-mode=dxc -T cs_6_6 -spirv %s -O3 -E main [[vk::ext_builtin_input(/* NumWorkGroups */ 24)]] static const uint3 input; [[vk::ext_builtin_output(/* Random */ 25)]] static uint3 output; [shader("compute")] [numthreads(32, 1, 1)] void main(uint3 id : SV_GroupID, uint3 id2 : SV_GroupID) { output = input + id2 + id; } ``` Note: this code wouldn't pass validation because the output built-in is invalid. From b0c306dbbaf30740da23b6ba1c3291807247d6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brio...@google.com> Date: Fri, 15 Nov 2024 15:51:17 +0100 Subject: [PATCH] [SPIR-V] DRAFT: Shader built-ins - no spec change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Draft PR to explore adding semantics & inline SPIR-V for builtins. This PR is an alternative to #115187 which does not requires a spec change as we keep the variables as `static [const]`. In addition, it tried to remain closer to DXIL by using a load/store builtin intrinsic instead of relying on an external global variable (IR level). ``` // RUN: %clang --driver-mode=dxc -T cs_6_6 -spirv %s -O3 -E main [[vk::ext_builtin_input(/* NumWorkGroups */ 24)]] static const uint3 input; [[vk::ext_builtin_output(/* Random */ 25)]] static uint3 output; [shader("compute")] [numthreads(32, 1, 1)] void main(uint3 id : SV_GroupID, uint3 id2 : SV_GroupID) { output = input + id2 + id; } ``` Note: this code wouldn't pass validation because the output built-in is invalid. Signed-off-by: Nathan Gauër <brio...@google.com> --- clang/include/clang/Basic/AddressSpaces.h | 3 + clang/include/clang/Basic/Attr.td | 33 ++++++++ clang/include/clang/Basic/AttrDocs.td | 31 +++++++ .../include/clang/Basic/AttributeCommonInfo.h | 2 +- clang/include/clang/Sema/SemaHLSL.h | 2 + clang/lib/AST/Decl.cpp | 4 + clang/lib/AST/TypePrinter.cpp | 2 + clang/lib/Basic/Attributes.cpp | 3 +- clang/lib/Basic/TargetInfo.cpp | 1 + clang/lib/Basic/Targets/AArch64.h | 1 + clang/lib/Basic/Targets/AMDGPU.cpp | 2 + clang/lib/Basic/Targets/DirectX.h | 1 + clang/lib/Basic/Targets/NVPTX.h | 1 + clang/lib/Basic/Targets/SPIR.h | 2 + clang/lib/Basic/Targets/SystemZ.h | 1 + clang/lib/Basic/Targets/TCE.h | 1 + clang/lib/Basic/Targets/WebAssembly.h | 41 +++++----- clang/lib/Basic/Targets/X86.h | 1 + clang/lib/CodeGen/CGDeclCXX.cpp | 18 ++++- clang/lib/CodeGen/CGHLSLRuntime.cpp | 74 ++++++++++++++++- clang/lib/CodeGen/CGHLSLRuntime.h | 7 ++ clang/lib/CodeGen/CodeGenModule.cpp | 12 ++- clang/lib/Parse/ParseHLSL.cpp | 1 + clang/lib/Sema/SemaDecl.cpp | 7 ++ clang/lib/Sema/SemaDeclAttr.cpp | 9 +++ clang/lib/Sema/SemaHLSL.cpp | 64 +++++++++++++++ .../SemaTemplate/address_space-dependent.cpp | 4 +- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 3 + llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 2 +- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 80 ++++++++++++++++++- llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 5 +- llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 4 + llvm/lib/Target/SPIRV/SPIRVUtils.h | 6 +- .../kernel-argument-pointer-addressspace.ll | 22 ++++- 34 files changed, 413 insertions(+), 37 deletions(-) diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h index 7b723d508fff17..2157ae488cf088 100644 --- a/clang/include/clang/Basic/AddressSpaces.h +++ b/clang/include/clang/Basic/AddressSpaces.h @@ -59,6 +59,9 @@ enum class LangAS : unsigned { // HLSL specific address spaces. hlsl_groupshared, + // Vulkan specific address spaces. + vulkan_private, + // Wasm specific address spaces. wasm_funcref, diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 6035a563d5fce7..04a054c75690da 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -164,6 +164,16 @@ def HLSLBufferObj : SubsetSubject<HLSLBuffer, [{isa<HLSLBufferDecl>(S)}], "cbuffer/tbuffer">; +def HLSLInputBuiltin : SubsetSubject<Var, + [{S->hasGlobalStorage() && S->getType().isConstQualified() && + S->getStorageClass()==StorageClass::SC_Static}], + "static const global variables">; + +def HLSLOutputBuiltin : SubsetSubject<Var, + [{S->hasGlobalStorage() && !S->getType().isConstQualified() && + S->getStorageClass()==StorageClass::SC_Static}], + "static const global variables">; + def ClassTmpl : SubsetSubject<CXXRecord, [{S->getDescribedClassTemplate()}], "class templates">; @@ -4621,6 +4631,22 @@ def HLSLNumThreads: InheritableAttr { let Documentation = [NumThreadsDocs]; } +def HLSLVkExtBuiltinInput: InheritableAttr { + let Spellings = [CXX11<"vk", "ext_builtin_input">]; + let Args = [IntArgument<"BuiltIn">]; + let Subjects = SubjectList<[HLSLInputBuiltin], ErrorDiag>; + let LangOpts = [HLSL]; + let Documentation = [VkExtBuiltinInputDocs]; +} + +def HLSLVkExtBuiltinOutput: InheritableAttr { + let Spellings = [CXX11<"vk", "ext_builtin_output">]; + let Args = [IntArgument<"BuiltIn">]; + let Subjects = SubjectList<[HLSLOutputBuiltin], ErrorDiag>; + let LangOpts = [HLSL]; + let Documentation = [VkExtBuiltinOutputDocs]; +} + def HLSLSV_GroupIndex: HLSLAnnotationAttr { let Spellings = [HLSLAnnotation<"SV_GroupIndex">]; let Subjects = SubjectList<[ParmVar, GlobalVar]>; @@ -4628,6 +4654,13 @@ def HLSLSV_GroupIndex: HLSLAnnotationAttr { let Documentation = [HLSLSV_GroupIndexDocs]; } +def HLSLSV_GroupID: HLSLAnnotationAttr { + let Spellings = [HLSLAnnotation<"SV_GroupID">]; + let Subjects = SubjectList<[ParmVar, GlobalVar]>; + let LangOpts = [HLSL]; + let Documentation = [HLSLSV_GroupIDDocs]; +} + def HLSLResourceBinding: InheritableAttr { let Spellings = [HLSLAnnotation<"register">]; let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar], ErrorDiag>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 2fdceca163ee63..5d5548b71a57a8 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7746,6 +7746,26 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo }]; } +def VkExtBuiltinInputDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``vk::ext_builtin_input`` attribute applies to HLSL global variables. +The ``BuiltIn`` value is the ID of the BuiltIn in the SPIR-V specification. + +The full documentation is available here: https://microsoft.github.io/hlsl-specs/proposals/0011-inline-spirv.html + }]; +} + +def VkExtBuiltinOutputDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``vk::ext_builtin_output`` attribute applies to HLSL global variables. +The ``BuiltIn`` value is the ID of the BuiltIn in the SPIR-V specification. + +The full documentation is available here: https://microsoft.github.io/hlsl-specs/proposals/0011-inline-spirv.html + }]; +} + def HLSLSV_ShaderTypeAttrDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -7904,6 +7924,17 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windo }]; } +def HLSLSV_GroupIDDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``SV_GroupID`` semantic, when applied to an input parameter, specifies a +data binding to map the group index to the specified parameter. This attribute +is only supported in compute shaders. + +The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupid + }]; +} + def HLSLResourceBindingDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h index 11c64547721739..aac1eb61b86039 100644 --- a/clang/include/clang/Basic/AttributeCommonInfo.h +++ b/clang/include/clang/Basic/AttributeCommonInfo.h @@ -67,7 +67,7 @@ class AttributeCommonInfo { IgnoredAttribute, UnknownAttribute, }; - enum class Scope { NONE, CLANG, GNU, MSVC, OMP, HLSL, GSL, RISCV }; + enum class Scope { NONE, CLANG, GNU, MSVC, OMP, HLSL, GSL, RISCV, VULKAN }; private: const IdentifierInfo *AttrName = nullptr; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 06c541dec08cc8..d3ec45a367ae41 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -117,6 +117,8 @@ class SemaHLSL : public SemaBase { void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc); void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL); + void handleVkExtBuiltinInput(Decl *D, const ParsedAttr &AL); + void handleVkExtBuiltinOutput(Decl *D, const ParsedAttr &AL); void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL); void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL); void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index f33d2fb1530d17..f015d9e83fb277 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2830,6 +2830,10 @@ VarDecl::needsDestruction(const ASTContext &Ctx) const { if (Eval->HasConstantDestruction) return QualType::DK_none; + if (hasAttr<HLSLVkExtBuiltinOutputAttr>()) { + return QualType::DK_cxx_destructor; + } + if (isNoDestroy(Ctx)) return QualType::DK_none; diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index df9acd387bf770..23ab877694ffc9 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2555,6 +2555,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) { return "__funcref"; case LangAS::hlsl_groupshared: return "groupshared"; + case LangAS::vulkan_private: + return "Private"; default: return std::to_string(toTargetAddressSpace(AS)); } diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index 6904bce3ac51ec..3d7456bf6e3e28 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -166,7 +166,8 @@ getScopeFromNormalizedScopeName(StringRef ScopeName) { .Case("hlsl", AttributeCommonInfo::Scope::HLSL) .Case("msvc", AttributeCommonInfo::Scope::MSVC) .Case("omp", AttributeCommonInfo::Scope::OMP) - .Case("riscv", AttributeCommonInfo::Scope::RISCV); + .Case("riscv", AttributeCommonInfo::Scope::RISCV) + .Case("vk", AttributeCommonInfo::Scope::VULKAN); } unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 86befb1cbc74fc..c4024654234523 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -47,6 +47,7 @@ static const LangASMap FakeAddrSpaceMap = { 11, // ptr32_uptr 12, // ptr64 13, // hlsl_groupshared + 14, // vulkan_private 20, // wasm_funcref }; diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 4c25bdb5bb16df..9f96f41ef724b9 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -44,6 +44,7 @@ static const unsigned ARM64AddrSpaceMap[] = { static_cast<unsigned>(AArch64AddrSpace::ptr32_uptr), static_cast<unsigned>(AArch64AddrSpace::ptr64), 0, // hlsl_groupshared + 0, // vulkan_private // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 20, // wasm_funcref diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index 99f8f2944e2796..3896ae1a94f6b0 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -59,6 +59,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = { llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64 llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared + llvm::AMDGPUAS::FLAT_ADDRESS, // vulkan_private }; const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { @@ -83,6 +84,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64 llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared + llvm::AMDGPUAS::FLAT_ADDRESS, // vulkan_private }; } // namespace targets diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h index ab22d1281a4df7..40c9b64fadffd5 100644 --- a/clang/lib/Basic/Targets/DirectX.h +++ b/clang/lib/Basic/Targets/DirectX.h @@ -42,6 +42,7 @@ static const unsigned DirectXAddrSpaceMap[] = { 0, // ptr32_uptr 0, // ptr64 3, // hlsl_groupshared + 0, // vulkan_private // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 20, // wasm_funcref diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index 165b28a60fb2a9..c5838680a4e31c 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -45,6 +45,7 @@ static const unsigned NVPTXAddrSpaceMap[] = { 0, // ptr32_uptr 0, // ptr64 0, // hlsl_groupshared + 0, // vulkan_private // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 20, // wasm_funcref diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 85e4bd920d8535..0ee5428e82d371 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -47,6 +47,7 @@ static const unsigned SPIRDefIsPrivMap[] = { 0, // ptr32_uptr 0, // ptr64 0, // hlsl_groupshared + 7, // vulkan_private // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 20, // wasm_funcref @@ -80,6 +81,7 @@ static const unsigned SPIRDefIsGenMap[] = { 0, // ptr32_uptr 0, // ptr64 0, // hlsl_groupshared + 7, // vulkan_private // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 20, // wasm_funcref diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index ef9a07033a6e4f..f58f9ed3a8cb49 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -42,6 +42,7 @@ static const unsigned ZOSAddressMap[] = { 1, // ptr32_uptr 0, // ptr64 0, // hlsl_groupshared + 0, // vulkan_private 0 // wasm_funcref }; diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h index d6280b02f07b25..3f3658eb559d92 100644 --- a/clang/lib/Basic/Targets/TCE.h +++ b/clang/lib/Basic/Targets/TCE.h @@ -51,6 +51,7 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = { 0, // ptr32_uptr 0, // ptr64 0, // hlsl_groupshared + 0, // vulkan_private // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 20, // wasm_funcref diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index 6c2fe8049ff47a..4029ea372485b5 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -22,26 +22,27 @@ namespace clang { namespace targets { static const unsigned WebAssemblyAddrSpaceMap[] = { - 0, // Default - 0, // opencl_global - 0, // opencl_local - 0, // opencl_constant - 0, // opencl_private - 0, // opencl_generic - 0, // opencl_global_device - 0, // opencl_global_host - 0, // cuda_device - 0, // cuda_constant - 0, // cuda_shared - 0, // sycl_global - 0, // sycl_global_device - 0, // sycl_global_host - 0, // sycl_local - 0, // sycl_private - 0, // ptr32_sptr - 0, // ptr32_uptr - 0, // ptr64 - 0, // hlsl_groupshared + 0, // Default + 0, // opencl_global + 0, // opencl_local + 0, // opencl_constant + 0, // opencl_private + 0, // opencl_generic + 0, // opencl_global_device + 0, // opencl_global_host + 0, // cuda_device + 0, // cuda_constant + 0, // cuda_shared + 0, // sycl_global + 0, // sycl_global_device + 0, // sycl_global_host + 0, // sycl_local + 0, // sycl_private + 0, // ptr32_sptr + 0, // ptr32_uptr + 0, // ptr64 + 0, // hlsl_groupshared + 0, // vulkan_private 20, // wasm_funcref }; diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 06a7eed8177cb2..1b6e2d2a532175 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -46,6 +46,7 @@ static const unsigned X86AddrSpaceMap[] = { 271, // ptr32_uptr 272, // ptr64 0, // hlsl_groupshared + 0, // vulkan_private // Wasm address space values for this target are dummy values, // as it is only enabled for Wasm targets. 20, // wasm_funcref diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 2c3054605ee754..c0d5ebbb84fac7 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -45,6 +45,8 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, if (lv.isObjCStrong()) CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init), DeclPtr, D.getTLSKind()); + else if (D.hasAttr<HLSLVkExtBuiltinInputAttr>()) + CGM.getHLSLRuntime().EmitBuiltinConstructor(CGF, D, DeclPtr); else if (lv.isObjCWeak()) CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init), DeclPtr); @@ -79,6 +81,15 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, QualType::DestructionKind DtorKind = D.needsDestruction(CGF.getContext()); // FIXME: __attribute__((cleanup)) ? + CodeGenModule &CGM = CGF.CGM; + + if (D.hasAttr<HLSLVkExtBuiltinOutputAttr>()) { + llvm::Constant *Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy); + llvm::FunctionCallee Func = + CGF.CGM.getHLSLRuntime().EmitBuiltinDestructor(D, Addr); + CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument); + return; + } switch (DtorKind) { case QualType::DK_none: @@ -97,8 +108,6 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, llvm::FunctionCallee Func; llvm::Constant *Argument; - - CodeGenModule &CGM = CGF.CGM; QualType Type = D.getType(); // Special-case non-array C++ destructors, if they have the right signature. @@ -1177,6 +1186,11 @@ void CodeGenFunction::GenerateCXXGlobalCleanUpFunc( // Make sure the call and the callee agree on calling convention. if (llvm::Function *F = dyn_cast<llvm::Function>(Callee)) CI->setCallingConv(F->getCallingConv()); + + // This is required if the destructor is marked as convergent. + if (CGM.shouldEmitConvergenceTokens() && CI->isConvergent()) { + addControlledConvergenceToken(CI); + } } } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 7ba0d615018181..d64e12e5eb277d 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -14,6 +14,7 @@ #include "CGHLSLRuntime.h" #include "CGDebugInfo.h" +#include "CodeGenFunction.h" #include "CodeGenModule.h" #include "TargetInfo.h" #include "clang/AST/Decl.h" @@ -379,6 +380,18 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B, const ParmVarDecl &D, llvm::Type *Ty) { assert(D.hasAttrs() && "Entry parameter missing annotation attribute!"); + + if (D.hasAttr<HLSLSV_GroupIDAttr>()) { + if (getArch() == llvm::Triple::spirv) { + llvm::Type *Ty = CGM.getTypes().ConvertTypeForMem(D.getType()); + llvm::Function *IntrinsicID = + CGM.getIntrinsic(Intrinsic::spv_load_builtin, {Ty}); + return B.CreateCall(IntrinsicID, {B.getInt32(/* WorkgroupID */ 26)}); + } else + // FIXME: getIntrinsic(getGroupIDIntrinsic()) + return nullptr; + } + if (D.hasAttr<HLSLSV_GroupIndexAttr>()) { llvm::Function *DxGroupIndex = CGM.getIntrinsic(Intrinsic::dx_flattened_thread_id_in_group); @@ -503,13 +516,17 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() { IP = Token->getNextNode(); } IRBuilder<> B(IP); - for (auto *Fn : CtorFns) - B.CreateCall(FunctionCallee(Fn), {}, OB); + for (auto *Fn : CtorFns) { + CallInst *CI = B.CreateCall(FunctionCallee(Fn), {}, OB); + CI->setCallingConv(Fn->getCallingConv()); + } // Insert global dtors before the terminator of the last instruction B.SetInsertPoint(F.back().getTerminator()); - for (auto *Fn : DtorFns) - B.CreateCall(FunctionCallee(Fn), {}, OB); + for (auto *Fn : DtorFns) { + CallInst *CI = B.CreateCall(FunctionCallee(Fn), {}, OB); + CI->setCallingConv(Fn->getCallingConv()); + } } // No need to keep global ctors/dtors for non-lib profile after call to @@ -608,6 +625,55 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() { return InitResBindingsFunc; } +void CGHLSLRuntime::EmitBuiltinConstructor(CodeGenFunction &CGF, + const VarDecl &VD, Address dst) { + HLSLVkExtBuiltinInputAttr *BuiltinAttr = + VD.getAttr<HLSLVkExtBuiltinInputAttr>(); + assert(BuiltinAttr); + + CGBuilderTy &B = CGF.Builder; + llvm::Type *Ty = CGF.ConvertTypeForMem(VD.getType()); + llvm::Function *IntrinsicID = + CGM.getIntrinsic(Intrinsic::spv_load_builtin, {Ty}); + + llvm::Value *Value = + B.CreateCall(IntrinsicID, {B.getInt32(BuiltinAttr->getBuiltIn())}); + B.CreateStore(Value, dst); +} + +llvm::Function *CGHLSLRuntime::EmitBuiltinDestructor(const VarDecl &VD, + Address dst) { + HLSLVkExtBuiltinOutputAttr *BuiltinAttr = + VD.getAttr<HLSLVkExtBuiltinOutputAttr>(); + assert(BuiltinAttr); + + CodeGenFunction CGF(CGM); + FunctionArgList args; + ASTContext &Ctx = CGM.getContext(); + ImplicitParamDecl Dst(Ctx, Ctx.VoidPtrTy, ImplicitParamKind::Other); + args.push_back(&Dst); + const CGFunctionInfo &FI = + CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, args); + llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); + llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction( + FTy, "__cxx_global_array_dtor", FI, VD.getLocation()); + + CGF.StartFunction(GlobalDecl(&VD, DynamicInitKind::GlobalArrayDestructor), + Ctx.VoidTy, fn, FI, args); + + CGBuilderTy &B = CGF.Builder; + llvm::Type *Ty = CGF.ConvertTypeForMem(VD.getType()); + llvm::Function *IntrinsicID = + CGM.getIntrinsic(Intrinsic::spv_store_builtin, {Ty}); + + llvm::Value *V = B.CreateLoad(dst); + B.CreateCall(IntrinsicID, {B.getInt32(BuiltinAttr->getBuiltIn()), V}); + + CGF.FinishFunction(); + + return fn; +} + llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) { if (!CGM.shouldEmitConvergenceTokens()) return nullptr; diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 381a5959ec098e..5d5f1c121c1de5 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -15,11 +15,14 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H +#include "CodeGenFunction.h" + #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/IntrinsicsSPIRV.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/HLSLRuntime.h" @@ -153,6 +156,10 @@ class CGHLSLRuntime { llvm::Function *createResourceBindingInitFn(); llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB); + void EmitBuiltinConstructor(CodeGenFunction &CGF, const VarDecl &VD, + Address dst); + llvm::Function *EmitBuiltinDestructor(const VarDecl &VD, Address dst); + private: void addBufferResourceAnnotation(llvm::GlobalVariable *GV, llvm::hlsl::ResourceClass RC, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index ba376f9ecfacde..c64f534f8bf28e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5047,6 +5047,10 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, if (LangOpts.OpenMP && !LangOpts.OpenMPSimd) getOpenMPRuntime().registerTargetGlobalVariable(D, GV); + // HLSL related end of code gen work items. + if (LangOpts.HLSL) + getHLSLRuntime().handleGlobalVarDefinition(D, GV); + // FIXME: This code is overly simple and should be merged with other global // handling. GV->setConstant(D->getType().isConstantStorage(getContext(), false, false)); @@ -5628,8 +5632,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, getCUDARuntime().handleVarRegistration(D, *GV); } - if (LangOpts.HLSL) - getHLSLRuntime().handleGlobalVarDefinition(D, GV); + if (LangOpts.HLSL) { + if (D->hasAttr<HLSLVkExtBuiltinInputAttr>()) + NeedsGlobalCtor = true; + if (D->hasAttr<HLSLVkExtBuiltinOutputAttr>()) + NeedsGlobalDtor = true; + } GV->setInitializer(Init); if (emitter) diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp index b36ea4012c26e1..1f95a3268e84e6 100644 --- a/clang/lib/Parse/ParseHLSL.cpp +++ b/clang/lib/Parse/ParseHLSL.cpp @@ -281,6 +281,7 @@ void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs, Diag(Loc, diag::err_unknown_hlsl_semantic) << II; return; case ParsedAttr::AT_HLSLSV_GroupIndex: + case ParsedAttr::AT_HLSLSV_GroupID: case ParsedAttr::AT_HLSLSV_DispatchThreadID: break; default: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 07ac6a3bb4e5b1..b738e757703bd9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14172,6 +14172,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { if (getLangOpts().OpenCL && Var->getType().getAddressSpace() == LangAS::opencl_local) return; + + // Don't give default value to Vulkan built-ins. + if (getLangOpts().HLSL && (Var->hasAttr<HLSLVkExtBuiltinInputAttr>() || + Var->hasAttr<HLSLVkExtBuiltinOutputAttr>())) { + return; + } + // C++03 [dcl.init]p9: // If no initializer is specified for an object, and the // object is of (possibly cv-qualified) non-POD class type (or diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 379d348cdbebad..b93eb1925d242d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7105,12 +7105,21 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_HLSLNumThreads: S.HLSL().handleNumThreadsAttr(D, AL); break; + case ParsedAttr::AT_HLSLVkExtBuiltinInput: + S.HLSL().handleVkExtBuiltinInput(D, AL); + break; + case ParsedAttr::AT_HLSLVkExtBuiltinOutput: + S.HLSL().handleVkExtBuiltinOutput(D, AL); + break; case ParsedAttr::AT_HLSLWaveSize: S.HLSL().handleWaveSizeAttr(D, AL); break; case ParsedAttr::AT_HLSLSV_GroupIndex: handleSimpleAttribute<HLSLSV_GroupIndexAttr>(S, D, AL); break; + case ParsedAttr::AT_HLSLSV_GroupID: + handleSimpleAttribute<HLSLSV_GroupIDAttr>(S, D, AL); + break; case ParsedAttr::AT_HLSLGroupSharedAddressSpace: handleSimpleAttribute<HLSLGroupSharedAddressSpaceAttr>(S, D, AL); break; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 65b0d9cd65637f..ba314938d3b904 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -434,6 +434,7 @@ void SemaHLSL::CheckSemanticAnnotation( switch (AnnotationAttr->getKind()) { case attr::HLSLSV_DispatchThreadID: case attr::HLSLSV_GroupIndex: + case attr::HLSLSV_GroupID: if (ST == llvm::Triple::Compute) return; DiagnoseAttrStageMismatch(AnnotationAttr, ST, {llvm::Triple::Compute}); @@ -645,6 +646,69 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str()); } +namespace { + +std::optional<uint32_t> validateVkExtBuiltin(Decl *D, const ParsedAttr &AL, + ASTContext &Ctx, Sema &SemaRef) { + llvm::Triple::OSType OSType = Ctx.getTargetInfo().getTriple().getOS(); + if (!isa<VarDecl>(D)) { + // FIXME + SemaRef.Diag(AL.getLoc(), diag::err_hlsl_missing_resource_class); + return std::nullopt; + } + + if (OSType != llvm::Triple::OSType::Vulkan) { + // FIXME + SemaRef.Diag(AL.getLoc(), diag::err_hlsl_missing_resource_class); + return std::nullopt; + } + + uint32_t ID; + if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), ID)) { + // FIXME + SemaRef.Diag(AL.getLoc(), diag::err_hlsl_missing_resource_class); + return std::nullopt; + } + + return ID; +} + +} // anonymous namespace + +void SemaHLSL::handleVkExtBuiltinInput(Decl *D, const ParsedAttr &AL) { + std::optional<uint32_t> ID = + validateVkExtBuiltin(D, AL, getASTContext(), SemaRef); + if (!ID) + return; + + VarDecl *VD = cast<VarDecl>(D); + QualType NewType = SemaRef.Context.getAddrSpaceQualType( + VD->getType(), LangAS::vulkan_private); + VD->setType(NewType); + + HLSLVkExtBuiltinInputAttr *NewAttr = ::new (getASTContext()) + HLSLVkExtBuiltinInputAttr(getASTContext(), AL, *ID); + assert(NewAttr); + VD->addAttr(NewAttr); +} + +void SemaHLSL::handleVkExtBuiltinOutput(Decl *D, const ParsedAttr &AL) { + std::optional<uint32_t> ID = + validateVkExtBuiltin(D, AL, getASTContext(), SemaRef); + if (!ID) + return; + + VarDecl *VD = cast<VarDecl>(D); + QualType NewType = SemaRef.Context.getAddrSpaceQualType( + VD->getType(), LangAS::vulkan_private); + VD->setType(NewType); + + HLSLVkExtBuiltinOutputAttr *NewAttr = ::new (getASTContext()) + HLSLVkExtBuiltinOutputAttr(getASTContext(), AL, *ID); + assert(NewAttr); + VD->addAttr(NewAttr); +} + void SemaHLSL::handleNumThreadsAttr(Decl *D, const ParsedAttr &AL) { llvm::VersionTuple SMVersion = getASTContext().getTargetInfo().getTriple().getOSVersion(); diff --git a/clang/test/SemaTemplate/address_space-dependent.cpp b/clang/test/SemaTemplate/address_space-dependent.cpp index 2ca9b8007ab418..b4371a7a0709e7 100644 --- a/clang/test/SemaTemplate/address_space-dependent.cpp +++ b/clang/test/SemaTemplate/address_space-dependent.cpp @@ -43,7 +43,7 @@ void neg() { template <long int I> void tooBig() { - __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388586)}} + __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388585)}} } template <long int I> @@ -101,7 +101,7 @@ int main() { car<1, 2, 3>(); // expected-note {{in instantiation of function template specialization 'car<1, 2, 3>' requested here}} HasASTemplateFields<1> HASTF; neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}} - correct<0x7FFFE9>(); + correct<0x7FFFE8>(); tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650L>' requested here}} __attribute__((address_space(1))) char *x; diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index f29eb7ee22b2d2..fad097fcb94238 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -57,6 +57,9 @@ let TargetPrefix = "spv" in { NoCapture<ArgIndex<1>>, ImmArg<ArgIndex<0>>]>; + def int_spv_load_builtin : Intrinsic<[llvm_any_ty], [llvm_i32_ty], [IntrReadMem, IntrWillReturn]>; + def int_spv_store_builtin : Intrinsic<[], [llvm_i32_ty, llvm_any_ty], [IntrWriteMem, IntrWillReturn]>; + // The following intrinsic(s) are mirrored from IntrinsicsDirectX.td for HLSL support. def int_spv_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>; def int_spv_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp index 6f222883ee07de..84a84a2a076a65 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -689,7 +689,7 @@ Register SPIRVGlobalRegistry::buildGlobalVariable( if (IsConst && ST.isOpenCLEnv()) buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Constant, {}); - if (GVar && GVar->getAlign().valueOrOne().value() != 1) { + if (ST.isOpenCLEnv() && GVar && GVar->getAlign().valueOrOne().value() != 1) { unsigned Alignment = (unsigned)GVar->getAlign().valueOrOne().value(); buildOpDecorate(Reg, MIRBuilder, SPIRV::Decoration::Alignment, {Alignment}); } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 158314d23393ae..12a15f14bd350a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -263,6 +263,12 @@ class SPIRVInstructionSelector : public InstructionSelector { bool selectWaveReadLaneAt(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; + bool selectLoadBuiltin(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; + + bool selectStoreBuiltin(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; + bool selectUnmergeValues(MachineInstr &I) const; bool selectHandleFromBinding(Register &ResVReg, const SPIRVType *ResType, @@ -2000,6 +2006,72 @@ bool SPIRVInstructionSelector::selectWaveReadLaneAt(Register ResVReg, .addUse(I.getOperand(3).getReg()); } +/// Helper function for building a load instruction for loading a builtin global +/// variable of \p BuiltinValue value. +static Register +getOrCreateBuiltinVariable(MachineIRBuilder &MIRBuilder, + SPIRVType *VariableType, SPIRVGlobalRegistry *GR, + SPIRV::BuiltIn::BuiltIn BuiltinValue, + SPIRV::StorageClass::StorageClass StorageClass) { + + Register NewRegister = + MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass); + MIRBuilder.getMRI()->setType(NewRegister, + LLT::pointer(0, GR->getPointerSize())); + SPIRVType *PtrType = GR->getOrCreateSPIRVPointerType( + VariableType, MIRBuilder, SPIRV::StorageClass::Input); + GR->assignSPIRVTypeToVReg(PtrType, NewRegister, MIRBuilder.getMF()); + + // Set up the global OpVariable with the necessary builtin decorations. + return GR->buildGlobalVariable( + NewRegister, PtrType, getLinkStringForBuiltIn(BuiltinValue), nullptr, + StorageClass, nullptr, /* isConst= */ false, + /* HasLinkageTy= */ false, SPIRV::LinkageType::Import, MIRBuilder, false); +} + +bool SPIRVInstructionSelector::selectLoadBuiltin(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + assert(I.getNumOperands() == 3); + assert(I.getOperand(0).isReg()); + assert(I.getOperand(2).isReg()); + + MachineInstr *ImmInst = getVRegDef(*MRI, I.getOperand(2).getReg()); + assert(ImmInst->getOpcode() == TargetOpcode::G_CONSTANT); + uint32_t BuiltInID = ImmInst->getOperand(1).getCImm()->getZExtValue(); + + MachineIRBuilder MIRBuilder(I); + Register VarReg = getOrCreateBuiltinVariable( + MIRBuilder, ResType, &GR, (SPIRV::BuiltIn::BuiltIn)BuiltInID, + SPIRV::StorageClass::Input); + return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpLoad)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addUse(VarReg); +} + +bool SPIRVInstructionSelector::selectStoreBuiltin(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + assert(I.getNumOperands() == 3); + assert(I.getOperand(1).isReg()); + assert(I.getOperand(2).isReg()); + + MachineInstr *ImmInst = getVRegDef(*MRI, I.getOperand(1).getReg()); + assert(ImmInst->getOpcode() == TargetOpcode::G_CONSTANT); + uint32_t BuiltInID = ImmInst->getOperand(1).getCImm()->getZExtValue(); + + const SPIRVType *ValueType = GR.getSPIRVTypeForVReg(I.getOperand(2).getReg()); + + MachineIRBuilder MIRBuilder(I); + Register VarReg = getOrCreateBuiltinVariable( + MIRBuilder, ValueType, &GR, (SPIRV::BuiltIn::BuiltIn)BuiltInID, + SPIRV::StorageClass::Output); + return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpStore)) + .addUse(VarReg) + .addUse(I.getOperand(2).getReg()); +} + bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { @@ -2840,6 +2912,10 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectExtInst(ResVReg, ResType, I, CL::step, GL::Step); case Intrinsic::spv_radians: return selectExtInst(ResVReg, ResType, I, CL::radians, GL::Radians); + case Intrinsic::spv_load_builtin: + return selectLoadBuiltin(ResVReg, ResType, I); + case Intrinsic::spv_store_builtin: + return selectStoreBuiltin(ResVReg, ResType, I); // Discard intrinsics which we do not expect to actually represent code after // lowering or intrinsics which are not implemented but should not crash when // found in a customer's LLVM IR input. @@ -3340,8 +3416,10 @@ bool SPIRVInstructionSelector::selectGlobalValue( unsigned AddrSpace = GV->getAddressSpace(); SPIRV::StorageClass::StorageClass Storage = addressSpaceToStorageClass(AddrSpace, STI); + bool isIOVariable = Storage == SPIRV::StorageClass::Input || + Storage == SPIRV::StorageClass::Output; bool HasLnkTy = GV->getLinkage() != GlobalValue::InternalLinkage && - Storage != SPIRV::StorageClass::Function; + Storage != SPIRV::StorageClass::Function && !isIOVariable; SPIRV::LinkageType::LinkageType LnkType = (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) ? SPIRV::LinkageType::Import diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp index 460f0127d4ffcd..5abcc0f096b736 100644 --- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp @@ -112,6 +112,9 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { const LLT p5 = LLT::pointer(5, PSize); // Input, SPV_INTEL_usm_storage_classes (Device) const LLT p6 = LLT::pointer(6, PSize); // SPV_INTEL_usm_storage_classes (Host) + const LLT p7 = LLT::pointer(7, PSize); // Private + const LLT p8 = LLT::pointer(8, PSize); // Input + const LLT p9 = LLT::pointer(9, PSize); // Output // TODO: remove copy-pasting here by using concatenation in some way. auto allPtrsScalarsAndVectors = { @@ -148,7 +151,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1, p2, p3, p4, p5, p6}; - auto allPtrs = {p0, p1, p2, p3, p4, p5, p6}; + auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p9}; bool IsExtendedInts = ST.canUseExtension( diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index aeb2c29f7b8618..79e2d8c6fd3e94 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -204,7 +204,11 @@ addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI) { ? SPIRV::StorageClass::HostOnlyINTEL : SPIRV::StorageClass::CrossWorkgroup; case 7: + return SPIRV::StorageClass::Private; + case 8: return SPIRV::StorageClass::Input; + case 9: + return SPIRV::StorageClass::Output; default: report_fatal_error("Unknown address space"); } diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index 298b0b93b0e4d2..5e6114333853b0 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -164,8 +164,12 @@ storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC) { return 5; case SPIRV::StorageClass::HostOnlyINTEL: return 6; - case SPIRV::StorageClass::Input: + case SPIRV::StorageClass::Private: return 7; + case SPIRV::StorageClass::Input: + return 8; + case SPIRV::StorageClass::Output: + return 9; default: report_fatal_error("Unable to get address space id"); } diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll index 2665923cc4e708..5f872c1c9aa353 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll @@ -53,7 +53,7 @@ define spir_kernel void @test5(ptr addrspace(4) %arg1) !kernel_arg_addr_space !6 !6 = !{i32 4} -; CHECK-DAG: %[[#PTR6:]] = OpTypePointer Input %[[#INT]] +; CHECK-DAG: %[[#PTR6:]] = OpTypePointer Private %[[#INT]] ; CHECK-DAG: %[[#ARG:]] = OpFunctionParameter %[[#PTR6]] define spir_kernel void @test6(ptr addrspace(7) %arg1) !kernel_arg_addr_space !7 !kernel_arg_type !2 { @@ -62,3 +62,23 @@ define spir_kernel void @test6(ptr addrspace(7) %arg1) !kernel_arg_addr_space !7 } !7 = !{i32 7} + +; CHECK-DAG: %[[#PTR7:]] = OpTypePointer Input %[[#INT]] +; CHECK-DAG: %[[#ARG:]] = OpFunctionParameter %[[#PTR7]] + +define spir_kernel void @test7(ptr addrspace(8) %arg1) !kernel_arg_addr_space !8 !kernel_arg_type !2 { + %a = getelementptr inbounds i32, ptr addrspace(8) %arg1, i32 2 + ret void +} + +!8 = !{i32 8} + +; CHECK-DAG: %[[#PTR8:]] = OpTypePointer Output %[[#INT]] +; CHECK-DAG: %[[#ARG:]] = OpFunctionParameter %[[#PTR8]] + +define spir_kernel void @test8(ptr addrspace(9) %arg1) !kernel_arg_addr_space !9 !kernel_arg_type !2 { + %a = getelementptr inbounds i32, ptr addrspace(9) %arg1, i32 2 + ret void +} + +!9 = !{i32 9} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits