[clang] [HLSL] Add support for groupshared args (PR #181886)
Sarah Spall via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 17 11:19:35 PST 2026
https://github.com/spall created https://github.com/llvm/llvm-project/pull/181886
Add support for groupshared args to HLSL.
Some support for template errors and warnings still needs to be added in a follow up.
Closes #174472
>From 7ef759df97b3035569c72feb000c4fa18a583041 Mon Sep 17 00:00:00 2001
From: Sarah Spall <sarahspall at microsoft.com>
Date: Tue, 17 Feb 2026 10:53:18 -0800
Subject: [PATCH] groupshared arg support mostly
---
.../clang/Basic/DiagnosticSemaKinds.td | 7 ++
clang/lib/AST/ASTContext.cpp | 2 +
clang/lib/Sema/SemaDecl.cpp | 6 +-
clang/lib/Sema/SemaDeclAttr.cpp | 13 ++++
clang/lib/Sema/SemaModule.cpp | 12 +++
clang/lib/Sema/SemaOverload.cpp | 7 +-
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 12 +++
clang/lib/Sema/SemaType.cpp | 21 +++++-
.../CodeGenHLSL/groupsharedArgs/ArrTest.hlsl | 24 ++++++
.../groupsharedArgs/MatrixTest.hlsl | 20 +++++
.../groupsharedArgs/Overloads.hlsl | 38 ++++++++++
.../groupsharedArgs/Scalartest.hlsl | 18 +++++
.../groupsharedArgs/TemplateTest.hlsl | 38 ++++++++++
.../groupsharedArgs/VectorTest.hlsl | 22 ++++++
.../groupsharedArgs/ExplicitCast.hlsl | 13 ++++
.../groupsharedArgs/ExportNoInlineTest.hlsl | 19 +++++
.../Language/groupsharedArgs/InOut.hlsl | 74 +++++++++++++++++++
.../groupsharedArgs/NotGroupSharedTest.hlsl | 13 ++++
.../groupsharedArgs/Pre202xWarning.hlsl | 13 ++++
.../Language/groupsharedArgs/ScalarTest.hlsl | 13 ++++
clang/test/SemaHLSL/group_shared.hlsl | 11 +--
clang/test/SemaHLSL/group_shared_202x.hlsl | 3 -
22 files changed, 384 insertions(+), 15 deletions(-)
create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl
create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl
create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl
create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl
create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl
create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl
create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl
create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl
create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl
create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl
create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl
create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 85a023435ba23..377abf8d2c2ae 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13438,6 +13438,13 @@ def err_hlsl_rootsignature_entry: Error<
def err_hlsl_operator_unsupported : Error<
"the '%select{&|*|->}0' operator is unsupported in HLSL">;
+def warn_hlsl_groupshared_202x : Warning<
+ "support for groupshared parameter annotation not added until HLSL 202x">,
+ InGroup<HLSLAvailability>;
+def warn_hlsl_groupshared_inout : Warning<
+ "passing groupshared variable to a parameter annotated with inout. "
+ "See 'groupshared' parameter annotation added in 202x">,
+ InGroup<HLSLAvailability>;
def err_hlsl_param_qualifier_mismatch :
Error<"conflicting parameter qualifier %0 on parameter %1">;
def err_hlsl_vector_compound_assignment_truncation : Error<
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 3f63420cae91e..43f3a4278fc39 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7949,6 +7949,8 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
}
QualType ASTContext::getAdjustedParameterType(QualType T) const {
+ if (getLangOpts().HLSL && T.getAddressSpace() != LangAS::Default)
+ return getLValueReferenceType(T);
if (getLangOpts().HLSL && T->isConstantArrayType())
return getArrayParameterType(T);
if (T->isArrayType() || T->isFunctionType())
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4dfde4bf8cedf..32adfe393464d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15841,7 +15841,11 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
// WebAssembly allows reference types as parameters. Funcref in particular
// lives in a different address space.
!(T->isFunctionPointerType() &&
- T.getAddressSpace() == LangAS::wasm_funcref)) {
+ T.getAddressSpace() == LangAS::wasm_funcref) &&
+ // HLSL allows function arguments to be qualified with an address space
+ // if the groupshared annotation is used.
+ !(getLangOpts().HLSL &&
+ T.getAddressSpace() == LangAS::hlsl_groupshared)) {
Diag(NameLoc, diag::err_arg_with_address_space);
New->setInvalidDecl();
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 5dbff18fff7a9..64fd8811136e8 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -7262,6 +7262,19 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
return;
}
+ if (S.getLangOpts().HLSL && isa<FunctionDecl>(D) &&
+ AL.getKind() == ParsedAttr::AT_NoInline) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ for (const ParmVarDecl *PVD : FD->parameters()) {
+ if (PVD->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
+ S.Diag(AL.getLoc(), diag::err_hlsl_attr_incompatible)
+ << "'noinline'" << "'groupshared' parameter";
+ return;
+ }
+ }
+ }
+ }
+
// Check if argument population must delayed to after template instantiation.
bool MustDelayArgs = MustDelayAttributeArguments(AL);
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 8cb684fd5ae3b..8fc3464ed3e0c 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -943,6 +943,18 @@ static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) {
D->setInvalidDecl();
return false;
}
+
+ if (isa<FunctionDecl>(D)) {
+ FunctionDecl *FD = cast<FunctionDecl>(D);
+ for (const ParmVarDecl *PVD : FD->parameters()) {
+ if (PVD->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
+ S.Diag(D->getBeginLoc(), diag::err_hlsl_attr_incompatible)
+ << "'export'" << "'groupshared' parameter";
+ D->setInvalidDecl();
+ return false;
+ }
+ }
+ }
}
// C++20 [module.interface]p3:
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 81edf966de9e7..a80609d8db119 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -7357,8 +7357,13 @@ void Sema::AddOverloadCandidate(
QualType ParamType = Proto->getParamType(ArgIdx);
auto ParamABI = Proto->getExtParameterInfo(ArgIdx).getABI();
if (ParamABI == ParameterABI::HLSLOut ||
- ParamABI == ParameterABI::HLSLInOut)
+ ParamABI == ParameterABI::HLSLInOut) {
ParamType = ParamType.getNonReferenceType();
+ if (ParamABI == ParameterABI::HLSLInOut &&
+ Args[ArgIdx]->getType().getAddressSpace() ==
+ LangAS::hlsl_groupshared)
+ Diag(Args[ArgIdx]->getBeginLoc(), diag::warn_hlsl_groupshared_inout);
+ }
Candidate.Conversions[ConvIdx] = TryCopyInitialization(
*this, Args[ArgIdx], ParamType, SuppressUserConversions,
/*InOverloadResolution=*/true,
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e74c41517ecbf..780aa766118fa 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -788,6 +788,18 @@ static void instantiateDependentHLSLParamModifierAttr(
ParmVarDecl *NewParm = cast<ParmVarDecl>(New);
NewParm->addAttr(Attr->clone(S.getASTContext()));
+ // we might have already produced an error
+ // just don't change the type here because it will assert
+ // also need to produce an error because of all the ways
+ // templates can be used
+ if (const auto *RT = NewParm->getType()->getAs<LValueReferenceType>()) {
+ if (RT->getPointeeType().getAddressSpace() == LangAS::hlsl_groupshared) {
+ S.Diag(Attr->getLoc(), diag::err_hlsl_attr_incompatible)
+ << Attr << "'groupshared'";
+ return;
+ }
+ }
+
const Type *OldParmTy = cast<ParmVarDecl>(Old)->getType().getTypePtr();
if (OldParmTy->isDependentType() && Attr->isAnyOut())
NewParm->setType(S.HLSL().getInoutParameterType(NewParm->getType()));
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index a6d4b989cae3d..62aab39ab268d 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8955,11 +8955,24 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case ParsedAttr::AT_OpenCLLocalAddressSpace:
case ParsedAttr::AT_OpenCLConstantAddressSpace:
case ParsedAttr::AT_OpenCLGenericAddressSpace:
- case ParsedAttr::AT_HLSLGroupSharedAddressSpace:
case ParsedAttr::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state);
attr.setUsedAsTypeAttr();
break;
+ case ParsedAttr::AT_HLSLGroupSharedAddressSpace:
+ HandleAddressSpaceTypeAttribute(type, attr, state);
+ if (state.getDeclarator().getContext() == DeclaratorContext::Prototype) {
+ if (state.getSema().getLangOpts().getHLSLVersion() <
+ LangOptions::HLSL_202x)
+ state.getSema().Diag(attr.getLoc(), diag::warn_hlsl_groupshared_202x);
+
+ // Note: we don't check for the usage of HLSLParamModifiers in/out/inout
+ // here because the check in the AT_HLSLParamModifier case is sufficient
+ // regardless of the order of groupshared or in/out/inout specified in
+ // the parameter. And checking there produces a better error message.
+ }
+ attr.setUsedAsTypeAttr();
+ break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
distributeObjCPointerTypeAttr(state, attr, type);
@@ -9044,6 +9057,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case ParsedAttr::AT_HLSLParamModifier: {
HandleHLSLParamModifierAttr(state, type, attr, state.getSema());
+ if (attrs.hasAttribute(ParsedAttr::AT_HLSLGroupSharedAddressSpace)) {
+ state.getSema().Diag(attr.getLoc(), diag::err_hlsl_attr_incompatible)
+ << attr << "'groupshared'";
+ attr.setInvalid();
+ return;
+ }
attr.setUsedAsTypeAttr();
break;
}
diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl
new file mode 100644
index 0000000000000..4989275e6ee6d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s
+
+groupshared float4 SharedArr[64];
+
+// CHECK-LABEL: define hidden void @_Z2fnRA64_U3AS3Dv4_ff(ptr addrspace(3) noundef align 16 dereferenceable(1024) %Arr, float noundef nofpclass(nan inf) %F)
+// CHECK: [[ArrAddr:%.*]] = alloca ptr addrspace(3), align 4
+// CHECK: [[FAddr:%.*]] = alloca float, align 4
+// CHECK: store ptr addrspace(3) %Arr, ptr [[ArrAddr]], align 4
+// CHECK: store float %F, ptr [[FAddr]], align 4
+// CHECK: [[A:%.*]] = load float, ptr [[FAddr]], align 4
+// CHECK: [[Splat:%.*]] = insertelement <1 x float> poison, float [[A]], i64 0
+// CHECK: [[B:%.*]] = shufflevector <1 x float> [[Splat]], <1 x float> poison, <4 x i32> zeroinitializer
+// CHECK: [[C:%.*]] = load ptr addrspace(3), ptr [[ArrAddr]], align 4, !align !3
+// CHECK: [[ArrIdx:%.*]] = getelementptr inbounds [64 x <4 x float>], ptr addrspace(3) [[C]], i32 0, i32 5
+// CHECK: store <4 x float> [[B]], ptr addrspace(3) [[ArrIdx]], align 16
+// CHECK: ret void
+void fn(groupshared float4 Arr[64], float F) {
+ Arr[5] = F.xxxx;
+}
+
+[numthreads(4,1,1)]
+void main() {
+ fn(SharedArr, 6.0);
+}
diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl
new file mode 100644
index 0000000000000..b33e2f2d71185
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s
+
+groupshared float4x4 SharedData;
+
+// CHECK-LABEL: define hidden void @_Z3fn1RU3AS3u11matrix_typeILm4ELm4EfE(ptr addrspace(3) noundef align 4 dereferenceable(64) %Sh)
+// CHECK: [[ShAddr:%.*]] = alloca ptr addrspace(3), align 4
+// CHECK: store ptr addrspace(3) %Sh, ptr [[ShAddr]], align 4
+// CHECK: [[A:%.*]] = load ptr addrspace(3), ptr [[ShAddr]], align 4
+// CHECK: [[B:%.*]] = load <16 x float>, ptr addrspace(3) [[A]], align 4
+// CHECK: [[Matins:%.*]] = insertelement <16 x float> [[B]], float 5.000000e+00, i32 4
+// CHECK: store <16 x float> [[Matins]], ptr addrspace(3) [[A]], align 4
+// CHECK: ret void
+void fn1(groupshared float4x4 Sh) {
+ Sh[0][1] = 5.0;
+}
+
+[numthreads(4,1,1)]
+void main(uint3 TID : SV_GroupThreadID) {
+ fn1(SharedData);
+}
diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl
new file mode 100644
index 0000000000000..5576eed5b5043
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s
+
+// Verify we are calling the correct overloads
+void fn(groupshared float4 Arr[2]);
+void fn(inout float4 Arr[2]);
+
+void fn2(groupshared int4 Shared);
+void fn2(int4 Local);
+
+[numthreads(4,1,1)]
+void main() {
+ float4 Local[2] = {1.0.xxxx, 2.0.xxxx};
+// CHECK: call void @_Z2fnA2_Dv4_f
+ fn(Local);
+
+// CHECK: call void @_Z3fn2Dv4_i
+ fn2(11.xxxx);
+}
+
+// CHECK-LABEL: define hidden void @_Z2fnA2_Dv4_f(ptr noalias noundef align 16 %Arr)
+void fn(inout float4 Arr[2]) {
+ Arr[1] = 5.0.xxxx;
+}
+
+// CHECK-LABEL: define hidden void @_Z3fn2Dv4_i(<4 x i32> noundef %Local) #0 {
+void fn2(int4 Local) {
+ int X = Local.y;
+}
+
+// CHECK-LABEL: define hidden void @_Z2fnRA2_U3AS3Dv4_f(ptr addrspace(3) noundef align 16 dereferenceable(32) %Arr)
+void fn(groupshared float4 Arr[2]) {
+ Arr[1] = 7.0.xxxx;
+}
+
+// CHECK-LABEL: define hidden void @_Z3fn2RU3AS3Dv4_i(ptr addrspace(3) noundef align 16 dereferenceable(16) %Shared)
+void fn2(groupshared int4 Shared) {
+ Shared.x = 10;
+}
diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl
new file mode 100644
index 0000000000000..02303e449dd76
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -fnative-int16-type -triple dxil-pc-shadermodel6.2-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s
+
+groupshared uint16_t SharedData;
+
+// CHECK-LABEL: define hidden void @_Z3fn1RU3AS3t(ptr addrspace(3) noundef align 2 dereferenceable(2) %Sh)
+// CHECK: [[ShAddr:%.*]] = alloca ptr addrspace(3), align 4
+// CHECK: store ptr addrspace(3) %Sh, ptr [[ShAddr]], align 4
+// CHECK: [[A:%.*]] = load ptr addrspace(3), ptr [[ShAddr]], align 4
+// CHECK: store i16 5, ptr addrspace(3) [[A]], align 2
+// CHECK: ret void
+void fn1(groupshared uint16_t Sh) {
+ Sh = 5;
+}
+
+[numthreads(4, 1, 1)]
+void main(uint3 TID : SV_GroupThreadID) {
+ fn1(SharedData);
+}
diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl
new file mode 100644
index 0000000000000..6989abadf4ca9
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s
+
+// In the case the template type is specified the groupshared attribute is preserved in the type
+// CHECK-LABEL: define linkonce_odr hidden void @_Z4tfooIU3AS3Dv4_iEvT_S2_(ptr addrspace(3) noundef align 16 dereferenceable(16) %a, ptr addrspace(3) noundef align 16 dereferenceable(16) %b)
+// CHECK: [[AAddr:%.*]] = alloca ptr addrspace(3), align 4
+// CHECK: [[BAddr:%.*]] = alloca ptr addrspace(3), align 4
+// CHECK: store ptr addrspace(3) %a, ptr [[AAddr]], align 4
+// CHECK: store ptr addrspace(3) %b, ptr [[BAddr]], align 4
+// CHECK: [[C:%.*]] = load ptr addrspace(3), ptr [[BAddr]], align 4
+// CHECK: [[D:%.*]] = load <4 x i32>, ptr addrspace(3) [[C]], align 16
+// CHECK: [[E:%.*]] = load ptr addrspace(3), ptr [[AAddr]], align 4
+// CHECK: store <4 x i32> [[D]], ptr addrspace(3) [[E]], align 16
+// CHECK: ret void
+
+// In the case the template type is deduced the deduction is done on the non cv-qualified type (the address space is removed)
+// So the non groupshared version of the function is deduced
+// CHECK-LABEL: define linkonce_odr hidden void @_Z4tfooIDv4_iEvT_S1_(<4 x i32> noundef %a, <4 x i32> noundef %b)
+// CHECK: [[AAddr:%.*]] = alloca <4 x i32>, align 16
+// CHECK: [[BAddr:%.*]] = alloca <4 x i32>, align 16
+// CHECK: store <4 x i32> %a, ptr [[AAddr]], align 16
+// CHECK: store <4 x i32> %b, ptr [[BAddr]], align 16
+// CHECK: [[C:%.*]] = load <4 x i32>, ptr [[BAddr]], align 16
+// CHECK: store <4 x i32> [[C]], ptr [[AAddr]], align 16
+// CHECK: ret void
+template<typename T>
+void tfoo(T a, T b) {
+ a = b;
+}
+
+using ISF = groupshared int4;
+ISF SharedData1;
+ISF SharedData2;
+
+[numthreads(4, 1, 1)]
+void main(uint3 TID : SV_GroupThreadID) {
+ tfoo<ISF>(SharedData1, SharedData2);
+ tfoo(SharedData1, SharedData2);
+}
diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl
new file mode 100644
index 0000000000000..e61f8d2cdf43b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s
+
+groupshared float4 SharedData;
+
+// CHECK-LABEL: define hidden void @_Z3fn1RU3AS3Dv4_f(ptr addrspace(3) noundef align 16 dereferenceable(16) %Sh)
+// CHECK: [[ShAddr:%.*]] = alloca ptr addrspace(3), align 4
+// CHECK: [[Tmp:%.*]] = alloca <1 x float>, align 4
+// CHECK: store ptr addrspace(3) %Sh, ptr [[ShAddr]], align 4
+// CHECK: store <1 x float> splat (float 5.000000e+00), ptr [[Tmp]], align 4
+// CHECK: [[A:%.*]] = load <1 x float>, ptr [[Tmp]], align 4
+// CHECK: [[B:%.*]] = shufflevector <1 x float> [[A]], <1 x float> poison, <4 x i32> zeroinitializer
+// CHECK: [[C:%.*]] = load ptr addrspace(3), ptr [[ShAddr]], align 4
+// CHECK: store <4 x float> [[B]], ptr addrspace(3) [[C]], align 16
+// CHECK: ret void
+void fn1(groupshared float4 Sh) {
+ Sh = 5.0.xxxx;
+}
+
+[numthreads(4, 1, 1)]
+void main(uint3 TID : SV_GroupThreadID) {
+ fn1(SharedData);
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl
new file mode 100644
index 0000000000000..86e24f2aee550
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -fnative-half-type -fnative-int16-type -verify -Wconversion %s
+
+groupshared uint16_t SharedData;
+
+void fn1(groupshared half Sh) {
+// expected-note at -1{{candidate function not viable: cannot bind reference in generic address space to object in address space 'groupshared' in 1st argument}}
+ Sh = 5;
+}
+
+void fn2() {
+ fn1((half)SharedData);
+ // expected-error at -1{{no matching function for call to 'fn1'}}
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl
new file mode 100644
index 0000000000000..bdac2dc37ca20
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -verify -Wconversion %s
+
+export void fn1(groupshared uint Sh) {
+// expected-error at -1{{'export' attribute is not compatible with 'groupshared' parameter attribute}}
+ Sh = 5;
+}
+
+__attribute__((noinline)) void fn2(groupshared uint Sh) {
+// expected-error at -1{{'noinline' attribute is not compatible with 'groupshared' parameter attribute}}
+ Sh = 6;
+}
+
+template<typename T>
+void fn3(T A, T B) {
+ A = B;
+}
+
+//export template void fn3<groupshared uint3>(groupshared uint3 A, groupshared uint3 B);
+// //expected-error at -1{{'export' attribute is not compatible with 'groupshared' parameter attribute}}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl
new file mode 100644
index 0000000000000..bf57b4b786260
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -verify -Wconversion %s
+
+groupshared uint SharedData;
+
+void fn1(inout uint Sh) {
+ Sh = 5;
+}
+
+void fn2(inout groupshared uint Sh);
+// expected-error at -1{{'inout' attribute is not compatible with 'groupshared' attribute}}
+void fn3(in groupshared uint Sh);
+// expected-error at -1{{'in' attribute is not compatible with 'groupshared' attribute}}
+void fn4(out groupshared uint Sh);
+// expected-error at -1{{'out' attribute is not compatible with 'groupshared' attribute}}
+void fn5(groupshared inout uint Sh);
+// expected-error at -1{{'inout' attribute is not compatible with 'groupshared' attribute}}
+void fn6(groupshared in uint Sh);
+// expected-error at -1{{'in' attribute is not compatible with 'groupshared' attribute}}
+void fn7(groupshared out uint Sh);
+// expected-error at -1{{'out' attribute is not compatible with 'groupshared' attribute}}
+
+
+template<typename T>
+void fn8(inout T A);
+// expected-note at -1{{candidate template ignored: substitution failure [with T = groupshared uint]: 'inout' attribute is not compatible with 'groupshared' attribute}}
+
+template void fn8<groupshared uint>(inout groupshared uint A);
+// expected-error at -1{{'inout' attribute is not compatible with 'groupshared' attribute}}
+// expected-error at -2{{explicit instantiation of 'fn8' does not refer to a function template, variable template, member function, member class, or static data member}}
+
+template<typename T>
+void fn9(out T A);
+// expected-note at -1{{candidate template ignored: substitution failure [with T = groupshared uint]: 'out' attribute is not compatible with 'groupshared' attribute}}
+
+template void fn9<groupshared uint>(out groupshared uint A);
+// expected-error at -1{{'out' attribute is not compatible with 'groupshared' attribute}}
+// expected-error at -2{{explicit instantiation of 'fn9' does not refer to a function template, variable template, member function, member class, or static data member}}
+
+template<typename T>
+void fn10(in T A);
+// expected-note at -1{{candidate template ignored: substitution failure [with T = groupshared uint]: 'in' attribute is not compatible with 'groupshared' attribute}}
+
+template void fn10<groupshared uint>(in groupshared uint A);
+// expected-error at -1{{'in' attribute is not compatible with 'groupshared' attribute}}
+// expected-error at -2{{explicit instantiation of 'fn10' does not refer to a function template, variable template, member function, member class, or static data member}}
+
+// expected-note at +2{{candidate template ignored: substitution failure [with T = groupshared uint]: 'inout' attribute is not compatible with 'groupshared' attribute}}
+template<typename T>
+void fn11(inout T A, inout T B) {
+ A = B;
+}
+// expected-note at +2{{candidate template ignored: substitution failure [with T = groupshared uint]: 'out' attribute is not compatible with 'groupshared' attribute}}
+template<typename T>
+void fn12(out T A, out T B) {
+ A = B;
+}
+
+// expected-note at +2{{candidate template ignored: substitution failure [with T = groupshared uint]: 'in' attribute is not compatible with 'groupshared' attribute}}
+template<typename T>
+void fn13(in T A, in T B) {
+ A = B;
+}
+
+void fn0() {
+ fn1(SharedData);
+// expected-warning at -1{{passing groupshared variable to a parameter annotated with inout. See 'groupshared' parameter annotation added in 202x}}
+
+ fn11<groupshared uint>(SharedData, SharedData);
+// expected-error at -1{{no matching function for call to 'fn11'}}
+ fn12<groupshared uint>(SharedData, SharedData);
+// expected-error at -1{{no matching function for call to 'fn12'}}
+ fn13<groupshared uint>(SharedData, SharedData);
+// expected-error at -1{{no matching function for call to 'fn13'}}
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl
new file mode 100644
index 0000000000000..4929f7bdce51a
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -finclude-default-header -std=hlsl202x -fnative-half-type -fnative-int16-type -verify -Wconversion %s
+
+void fn1(groupshared half Sh) {
+// expected-note at -1{{candidate function not viable: cannot bind reference in generic address space to object in address space 'groupshared' in 1st argument}}
+ Sh = 5;
+}
+
+[numthreads(4, 1, 1)]
+void main(uint3 TID : SV_GroupThreadID) {
+ half tmp = 1.0;
+ fn1(tmp);
+ // expected-error at -1{{no matching function for call to 'fn1'}}
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl
new file mode 100644
index 0000000000000..ba9cee2611dcf
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl2018 -verify -Wconversion %s
+
+groupshared uint SharedData;
+
+void fn1(groupshared uint Sh) {
+// expected-warning at -1{{support for groupshared parameter annotation not added until HLSL 202x}}
+// expected-warning@*{{support for HLSL language version hlsl2018 is incomplete, recommend using hlsl202x instead}}
+ Sh = 5;
+}
+
+void fn2() {
+ fn1(SharedData);
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl
new file mode 100644
index 0000000000000..b9f093c7cc825
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -fnative-half-type -fnative-int16-type -verify -Wconversion %s
+
+groupshared uint16_t SharedData;
+
+void fn1(groupshared half Sh) {
+// expected-note at -1{{candidate function not viable: no known conversion from 'groupshared uint16_t' (aka 'groupshared unsigned short') to 'groupshared half &' for 1st argument}}
+ Sh = 5;
+}
+
+void fn2() {
+ fn1(SharedData);
+ // expected-error at -1{{no matching function for call to 'fn1'}}
+}
diff --git a/clang/test/SemaHLSL/group_shared.hlsl b/clang/test/SemaHLSL/group_shared.hlsl
index 0293ddd15eeb9..4df6cf73c4fc0 100644
--- a/clang/test/SemaHLSL/group_shared.hlsl
+++ b/clang/test/SemaHLSL/group_shared.hlsl
@@ -48,12 +48,7 @@
static groupshared float g;
};
- // expected-error at +1 {{parameter may not be qualified with an address space}}
- float foo2(groupshared float a) {
- return a;
- }
-
-// expected-note at +2 {{parameter may not be qualified with an address space}}
+// expected-note at +2 {{candidate template ignored: substitution failure [with T = GSF]}}
template<typename T>
T tfoo(T t) {
return t;
@@ -67,8 +62,7 @@ template<typename T>
// it is caused by return type check is after pointer check which is acceptable.
// expected-error at +1 {{pointers are unsupported in HLSL}}
groupshared void (*fp)();
-// expected-error at +2 {{pointers are unsupported in HLSL}}
-// expected-error at +1 {{parameter may not be qualified with an address space}}
+// expected-error at +1 {{pointers are unsupported in HLSL}}
void (*fp2)(groupshared float);
// NOTE: HLSL not support trailing return types.
// expected-warning@#func{{'auto' type specifier is a HLSL 202y extension}}
@@ -102,5 +96,4 @@ _Static_assert(S3<groupshared float>::value, "");
// Can you overload based on the qualifier?
void func(float f) {}
-// expected-error at +1 {{parameter may not be qualified with an address space}}
void func(groupshared float f) {}
diff --git a/clang/test/SemaHLSL/group_shared_202x.hlsl b/clang/test/SemaHLSL/group_shared_202x.hlsl
index 7ebc717384e94..b9e84202e637e 100644
--- a/clang/test/SemaHLSL/group_shared_202x.hlsl
+++ b/clang/test/SemaHLSL/group_shared_202x.hlsl
@@ -11,11 +11,8 @@
// expected-error@#func {{return type cannot be qualified with address space}}
auto func() -> groupshared void; // #func
-// expected-error@#func_gs {{parameter may not be qualified with an address space}}
auto func(float groupshared) -> void; // #func_gs
-
-// expected-error@#l {{parameter may not be qualified with an address space}}
// expected-warning@#l {{lambdas are a clang HLSL extension}}
auto l = [](groupshared float ) {}; // #l
More information about the cfe-commits
mailing list