[clang] [llvm] [SPIR-V] DRAFT: Shader built-ins - no spec change (PR #116393)
Nathan Gauër via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 15 07:08:53 PST 2024
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?= <brioche at 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 <brioche at 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}
More information about the cfe-commits
mailing list