[clang] 24bf26c - [HLSL] Add support for groupshared args (#181886)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 9 19:17:16 PDT 2026
Author: Sarah Spall
Date: 2026-03-09T19:17:12-07:00
New Revision: 24bf26c057553c58e576a7cb7df89a22d2fe6961
URL: https://github.com/llvm/llvm-project/commit/24bf26c057553c58e576a7cb7df89a22d2fe6961
DIFF: https://github.com/llvm/llvm-project/commit/24bf26c057553c58e576a7cb7df89a22d2fe6961.diff
LOG: [HLSL] Add support for groupshared args (#181886)
Add support for groupshared args to HLSL.
Some support for template errors and warnings still needs to be added in
a follow up (tracked by #182535)
Closes #174472
Added:
clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl
clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl
clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl
clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl
clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl
clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl
clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl
clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl
clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl
clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl
clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl
clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaModule.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Sema/SemaType.cpp
clang/test/SemaHLSL/group_shared.hlsl
clang/test/SemaHLSL/group_shared_202x.hlsl
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0e6b3f51a5231..32d980eeb294d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13557,6 +13557,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 d9e9ae062e8d7..d8d2fc23974c2 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -8055,6 +8055,8 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
}
QualType ASTContext::getAdjustedParameterType(QualType T) const {
+ if (getLangOpts().HLSL && T.getAddressSpace() == LangAS::hlsl_groupshared)
+ 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 53650e2083e44..b5e8e9ba62c21 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15862,7 +15862,11 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
// WebAssembly allows reference types as parameters. Funcref in particular
// lives in a
diff erent 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 1b7f41061061d..fba07876eb093 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -7293,6 +7293,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 6cada8eff0107..f8ea462549136 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -7474,8 +7474,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..972981d7c11fb 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()));
+ // If this is groupshared don't change the type because it will assert
+ // below. In this case we might have already produced an error but we
+ // must produce one here again 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 6406ee06e757b..2187f7c16eba5 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -9099,11 +9099,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);
@@ -9192,6 +9205,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..584ffeeaa646a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl
@@ -0,0 +1,19 @@
+// 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:%.*]] = getelementptr <16 x float>, ptr addrspace(3) [[A]], i32 0, i32 4
+// CHECK: store float 5.000000e+00, ptr addrspace(3) [[B]], 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..863a6f14d445b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl
@@ -0,0 +1,55 @@
+// 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;
+}
+
+// CHECK-LABEL: define linkonce_odr hidden void @_Z5tfoo2IDv4_iEvRU3AS3T_S3_(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: [[Z:%.*]] = load ptr addrspace(3), ptr [[BAddr]], align 4
+// CHECK: [[Y:%.*]] = load <4 x i32>, ptr addrspace(3) [[Z]], align 16
+// CHECK: [[X:%.*]] = load ptr addrspace(3), ptr [[AAddr]], align 4
+// CHECK: store <4 x i32> [[Y]], ptr addrspace(3) [[X]], align 16
+// CHECK: ret void
+template<typename T>
+void tfoo2(groupshared T a, groupshared 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);
+
+ tfoo2(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..83b4454c07c1e
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl
@@ -0,0 +1,31 @@
+// 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;
+}
+
+template<typename T>
+void fnT(T A, T B) {
+// expected-note at -1{{candidate function template not viable: cannot bind reference in generic address space to object in address space 'groupshared' in 1st argument}}
+ A = B;
+}
+
+template<typename T>
+void fnT2(groupshared T A, groupshared T B) {
+// expected-note at -1{{candidate function template not viable: cannot bind reference in generic address space to object in address space 'groupshared' in 1st argument}}
+ A = B;
+}
+
+void fn2() {
+ fn1((half)SharedData);
+ // expected-error at -1{{no matching function for call to 'fn1'}}
+ // not sure why someone would do this but want to make sure templates do something sane
+ fnT<groupshared half>((half)SharedData, (half)SharedData);
+ // expected-error at -1{{no matching function for call to 'fnT'}}
+
+ fnT2<half>((half)SharedData, (half)SharedData);
+ // expected-error at -1{{no matching function for call to 'fnT2'}}
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl
new file mode 100644
index 0000000000000..c120adb4a4fbc
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl
@@ -0,0 +1,20 @@
+// 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(groupshared T A, groupshared T B) {
+ A = B;
+}
+
+export template void fn3<uint>(groupshared uint A, groupshared uint B);
+template __attribute__((noinline)) void fn3<float>(groupshared float A, groupshared float B);
+// expected-error at -1{{'noinline' 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..e8ab07b7d3a77
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl
@@ -0,0 +1,90 @@
+// 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;
+}
+
+template<typename T>
+T fn14(inout groupshared T A) {
+// expected-error at -1{{'inout' attribute is not compatible with 'groupshared' attribute}}
+ return A;
+}
+template<typename T>
+T fn15(in groupshared T A) {
+// expected-error at -1{{'in' attribute is not compatible with 'groupshared' attribute}}
+ return A;
+}
+template<typename T>
+T fn16(out groupshared T A) {
+// expected-error at -1{{'out' attribute is not compatible with 'groupshared' attribute}}
+ return A;
+}
+
+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..2625b5769089b
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl
@@ -0,0 +1,21 @@
+// 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;
+}
+
+template<typename T>
+T fn2(groupshared T Sh) {
+// expected-note at -1{{candidate template ignored: cannot deduce a type for 'T' that would make 'groupshared T' equal 'half'}}
+ return Sh;
+}
+
+[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'}}
+ fn2(tmp);
+ // expected-error at -1{{no matching function for call to 'fn2'}}
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl
new file mode 100644
index 0000000000000..0fe2962c3b446
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl
@@ -0,0 +1,28 @@
+// 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;
+}
+
+template<typename T>
+void fnT(T A, T B) {
+ A = B;
+}
+
+template void fnT<groupshared int>(groupshared int A, groupshared int B);
+// expected-warning at -1{{support for groupshared parameter annotation not added until HLSL 202x}}
+// expected-warning at -2{{support for groupshared parameter annotation not added until HLSL 202x}}
+
+void fn2() {
+ fn1(SharedData);
+}
+
+template<typename T>
+T fn3(groupshared T A) {
+// expected-warning at -1{{support for groupshared parameter annotation not added until HLSL 202x}}
+ return A;
+}
diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl
new file mode 100644
index 0000000000000..e5db9bfc7a8a6
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl
@@ -0,0 +1,30 @@
+// 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;
+}
+
+template<typename T>
+void fnT(T A, T B) {
+// expected-note at -1{{candidate function template not viable: no known conversion from 'groupshared uint16_t' (aka 'groupshared unsigned short') to 'groupshared half &' for 1st argument}}
+ A = B;
+}
+
+template<typename T>
+T fn3(groupshared T A) {
+// expected-note at -1{{candidate function template not viable: no known conversion from 'groupshared uint16_t' (aka 'groupshared unsigned short') to 'groupshared half &' for 1st argument}}
+ return A;
+}
+
+void fn2() {
+ fn1(SharedData);
+ // expected-error at -1{{no matching function for call to 'fn1'}}
+ // not sure why anyone would do thats but just making sure templates are sane
+ fnT<groupshared half>(SharedData, SharedData);
+ // expected-error at -1{{no matching function for call to 'fnT'}}
+ fn3<half>(SharedData);
+ // expected-error at -1{{no matching function for call to 'fn3'}}
+}
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