Skip to content

Commit 678911a

Browse files
authored
[SYCL] Add template parameter support for num_simd_work_items attribute (#2510)
This patch 1. adds support for template parameter on [[intelfpga::num_simd_work_items()]] attribute 2. splits test/SemaSYCL/num_simd_work_items.cpp to separate files for host compilation (test/SemaSYCL/num_simd_work_items_host.cpp) and device compilation (test/SemaSYCL/num_simd_work_items_device.cpp) 3. makes changes to intel_reqd_sub_group_size attribute source codes to avoid duplication and reuse for the template parameter support. Signed-off-by: Soumi Manna <[email protected]>
1 parent fc5d54c commit 678911a

File tree

10 files changed

+109
-67
lines changed

10 files changed

+109
-67
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ def SYCLIntelKernelArgsRestrict : InheritableAttr {
12091209

12101210
def SYCLIntelNumSimdWorkItems : InheritableAttr {
12111211
let Spellings = [CXX11<"intelfpga","num_simd_work_items">];
1212-
let Args = [UnsignedArgument<"Number">];
1212+
let Args = [ExprArgument<"Value">];
12131213
let LangOpts = [SYCLIsDevice, SYCLIsHost];
12141214
let Subjects = SubjectList<[Function], ErrorDiag>;
12151215
let Documentation = [SYCLIntelNumSimdWorkItemsAttrDocs];
@@ -1300,7 +1300,7 @@ def LoopUnrollHint : InheritableAttr {
13001300
def IntelReqdSubGroupSize: InheritableAttr {
13011301
let Spellings = [GNU<"intel_reqd_sub_group_size">,
13021302
CXX11<"intel", "reqd_sub_group_size">];
1303-
let Args = [ExprArgument<"SubGroupSize">];
1303+
let Args = [ExprArgument<"Value">];
13041304
let Subjects = SubjectList<[Function, CXXMethod], ErrorDiag>;
13051305
let Documentation = [IntelReqdSubGroupSizeDocs];
13061306
let LangOpts = [OpenCL, SYCLIsDevice, SYCLIsHost];

clang/include/clang/Sema/Sema.h

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9986,7 +9986,9 @@ class Sema final {
99869986
Expr *E);
99879987
void AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
99889988
Expr **Exprs, unsigned Size);
9989-
9989+
template <typename AttrType>
9990+
void addIntelSYCLSingleArgFunctionAttr(Decl *D, const AttributeCommonInfo &CI,
9991+
Expr *E);
99909992
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
99919993
void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
99929994
bool IsPackExpansion);
@@ -10041,10 +10043,6 @@ class Sema final {
1004110043
bool checkAllowedSYCLInitializer(VarDecl *VD,
1004210044
bool CheckValueDependent = false);
1004310045

10044-
// Adds an intel_reqd_sub_group_size attribute to a particular declaration.
10045-
void addIntelReqdSubGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
10046-
Expr *E);
10047-
1004810046
//===--------------------------------------------------------------------===//
1004910047
// C++ Coroutines TS
1005010048
//
@@ -12836,6 +12834,31 @@ class Sema final {
1283612834
}
1283712835
};
1283812836

12837+
template <typename AttrType>
12838+
void Sema::addIntelSYCLSingleArgFunctionAttr(Decl *D,
12839+
const AttributeCommonInfo &CI,
12840+
Expr *E) {
12841+
assert(E && "Attribute must have an argument.");
12842+
12843+
if (!E->isInstantiationDependent()) {
12844+
Optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(getASTContext());
12845+
if (!ArgVal) {
12846+
Diag(E->getExprLoc(), diag::err_attribute_argument_type)
12847+
<< CI.getAttrName() << AANT_ArgumentIntegerConstant
12848+
<< E->getSourceRange();
12849+
return;
12850+
}
12851+
int32_t ArgInt = ArgVal->getSExtValue();
12852+
if (ArgInt <= 0) {
12853+
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
12854+
<< CI.getAttrName() << /*positive*/ 0;
12855+
return;
12856+
}
12857+
}
12858+
12859+
D->addAttr(::new (Context) AttrType(Context, CI, E));
12860+
}
12861+
1283912862
template <typename AttrType>
1284012863
void Sema::AddOneConstantValueAttr(Decl *D, const AttributeCommonInfo &CI,
1284112864
Expr *E) {

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
611611
FD->getAttr<IntelReqdSubGroupSizeAttr>()) {
612612
llvm::LLVMContext &Context = getLLVMContext();
613613
Optional<llvm::APSInt> ArgVal =
614-
A->getSubGroupSize()->getIntegerConstantExpr(FD->getASTContext());
614+
A->getValue()->getIntegerConstantExpr(FD->getASTContext());
615615
assert(ArgVal.hasValue() && "Not an integer constant expression");
616616
llvm::Metadata *AttrMDArgs[] = {llvm::ConstantAsMetadata::get(
617617
Builder.getInt32(ArgVal->getSExtValue()))};
@@ -629,8 +629,12 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
629629

630630
if (const SYCLIntelNumSimdWorkItemsAttr *A =
631631
FD->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
632-
llvm::Metadata *AttrMDArgs[] = {
633-
llvm::ConstantAsMetadata::get(Builder.getInt32(A->getNumber()))};
632+
llvm::LLVMContext &Context = getLLVMContext();
633+
Optional<llvm::APSInt> ArgVal =
634+
A->getValue()->getIntegerConstantExpr(FD->getASTContext());
635+
assert(ArgVal.hasValue() && "Not an integer constant expression");
636+
llvm::Metadata *AttrMDArgs[] = {llvm::ConstantAsMetadata::get(
637+
Builder.getInt32(ArgVal->getSExtValue()))};
634638
Fn->setMetadata("num_simd_work_items",
635639
llvm::MDNode::get(Context, AttrMDArgs));
636640
}

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2979,31 +2979,6 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
29792979
}
29802980

29812981
// Handles intel_reqd_sub_group_size.
2982-
void Sema::addIntelReqdSubGroupSizeAttr(Decl *D,
2983-
const AttributeCommonInfo &Attr,
2984-
Expr *E) {
2985-
if (!E)
2986-
return;
2987-
2988-
if (!E->isInstantiationDependent()) {
2989-
Optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(getASTContext());
2990-
if (!ArgVal) {
2991-
Diag(E->getExprLoc(), diag::err_attribute_argument_type)
2992-
<< Attr.getAttrName() << AANT_ArgumentIntegerConstant
2993-
<< E->getSourceRange();
2994-
return;
2995-
}
2996-
int32_t ArgInt = ArgVal->getSExtValue();
2997-
if (ArgInt <= 0) {
2998-
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
2999-
<< Attr.getAttrName() << /*positive*/ 0;
3000-
return;
3001-
}
3002-
}
3003-
3004-
D->addAttr(::new (Context) IntelReqdSubGroupSizeAttr(Context, Attr, E));
3005-
}
3006-
30072982
static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
30082983
if (S.LangOpts.SYCLIsHost)
30092984
return;
@@ -3013,7 +2988,7 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
30132988
if (D->getAttr<IntelReqdSubGroupSizeAttr>())
30142989
S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
30152990

3016-
S.addIntelReqdSubGroupSizeAttr(D, AL, E);
2991+
S.addIntelSYCLSingleArgFunctionAttr<IntelReqdSubGroupSizeAttr>(D, AL, E);
30172992
}
30182993

30192994
// Handles num_simd_work_items.
@@ -3022,23 +2997,13 @@ static void handleNumSimdWorkItemsAttr(Sema &S, Decl *D,
30222997
if (D->isInvalidDecl())
30232998
return;
30242999

3025-
uint32_t NumSimdWorkItems = 0;
3026-
const Expr *E = Attr.getArgAsExpr(0);
3027-
if (!checkUInt32Argument(S, Attr, E, NumSimdWorkItems, 0,
3028-
/*StrictlyUnsigned=*/true))
3029-
return;
3030-
3031-
if (NumSimdWorkItems == 0) {
3032-
S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
3033-
<< Attr << E->getSourceRange();
3034-
return;
3035-
}
3000+
Expr *E = Attr.getArgAsExpr(0);
30363001

30373002
if (D->getAttr<SYCLIntelNumSimdWorkItemsAttr>())
30383003
S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr;
30393004

3040-
D->addAttr(::new (S.Context) SYCLIntelNumSimdWorkItemsAttr(
3041-
S.Context, Attr, NumSimdWorkItems));
3005+
S.addIntelSYCLSingleArgFunctionAttr<SYCLIntelNumSimdWorkItemsAttr>(D, Attr,
3006+
E);
30423007
}
30433008

30443009
// Handles max_global_work_dim.

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,15 +2738,15 @@ void Sema::MarkDevice(void) {
27382738
KernelBody ? KernelBody->getAttr<SYCLSimdAttr>() : nullptr;
27392739
if (auto *Existing =
27402740
SYCLKernel->getAttr<IntelReqdSubGroupSizeAttr>()) {
2741-
if (getIntExprValue(Existing->getSubGroupSize(), getASTContext()) !=
2742-
getIntExprValue(Attr->getSubGroupSize(), getASTContext())) {
2741+
if (getIntExprValue(Existing->getValue(), getASTContext()) !=
2742+
getIntExprValue(Attr->getValue(), getASTContext())) {
27432743
Diag(SYCLKernel->getLocation(),
27442744
diag::err_conflicting_sycl_kernel_attributes);
27452745
Diag(Existing->getLocation(), diag::note_conflicting_attribute);
27462746
Diag(Attr->getLocation(), diag::note_conflicting_attribute);
27472747
SYCLKernel->setInvalidDecl();
27482748
}
2749-
} else if (KBSimdAttr && (getIntExprValue(Attr->getSubGroupSize(),
2749+
} else if (KBSimdAttr && (getIntExprValue(Attr->getValue(),
27502750
getASTContext()) != 1)) {
27512751
reportConflictingAttrs(*this, KernelBody, KBSimdAttr, Attr);
27522752
} else {

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -541,15 +541,16 @@ static void instantiateSYCLIntelPipeIOAttr(
541541
S.addSYCLIntelPipeIOAttr(New, *Attr, Result.getAs<Expr>());
542542
}
543543

544-
static void instantiateIntelReqdSubGroupSizeAttr(
544+
template <typename AttrName>
545+
static void instantiateIntelSYCLFunctionAttr(
545546
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
546-
const IntelReqdSubGroupSizeAttr *Attr, Decl *New) {
547-
// The SubGroupSize expression is a constant expression.
547+
const AttrName *Attr, Decl *New) {
548548
EnterExpressionEvaluationContext Unevaluated(
549549
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
550-
ExprResult Result = S.SubstExpr(Attr->getSubGroupSize(), TemplateArgs);
550+
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
551551
if (!Result.isInvalid())
552-
S.addIntelReqdSubGroupSizeAttr(New, *Attr, Result.getAs<Expr>());
552+
S.addIntelSYCLSingleArgFunctionAttr<AttrName>(New, *Attr,
553+
Result.getAs<Expr>());
553554
}
554555

555556
void Sema::InstantiateAttrsForDecl(
@@ -697,8 +698,14 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
697698
}
698699
if (const auto *IntelReqdSubGroupSize =
699700
dyn_cast<IntelReqdSubGroupSizeAttr>(TmplAttr)) {
700-
instantiateIntelReqdSubGroupSizeAttr(*this, TemplateArgs,
701-
IntelReqdSubGroupSize, New);
701+
instantiateIntelSYCLFunctionAttr<IntelReqdSubGroupSizeAttr>(
702+
*this, TemplateArgs, IntelReqdSubGroupSize, New);
703+
continue;
704+
}
705+
if (const auto *SYCLIntelNumSimdWorkItems =
706+
dyn_cast<SYCLIntelNumSimdWorkItemsAttr>(TmplAttr)) {
707+
instantiateIntelSYCLFunctionAttr<SYCLIntelNumSimdWorkItemsAttr>(
708+
*this, TemplateArgs, SYCLIntelNumSimdWorkItems, New);
702709
continue;
703710
}
704711
// Existing DLL attribute on the instantiation takes precedence.

clang/test/CodeGenSYCL/num-simd-work-items.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ class Foo {
55
[[intelfpga::num_simd_work_items(1)]] void operator()() const {}
66
};
77

8+
template <int SIZE>
9+
class Functor {
10+
public:
11+
[[intelfpga::num_simd_work_items(SIZE)]] void operator()() const {}
12+
};
13+
814
template <typename name, typename Func>
915
__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) {
1016
kernelFunc();
@@ -17,10 +23,13 @@ void bar() {
1723
kernel<class kernel_name2>(
1824
[]() [[intelfpga::num_simd_work_items(42)]] {});
1925

26+
Functor<2> f;
27+
kernel<class kernel_name3>(f);
2028
}
2129

2230
// CHECK: define spir_kernel void @{{.*}}kernel_name1() {{.*}} !num_simd_work_items ![[NUM1:[0-9]+]]
2331
// CHECK: define spir_kernel void @{{.*}}kernel_name2() {{.*}} !num_simd_work_items ![[NUM42:[0-9]+]]
32+
// CHECK: define spir_kernel void @{{.*}}kernel_name3() {{.*}} !num_simd_work_items ![[NUM2:[0-9]+]]
2433
// CHECK: ![[NUM1]] = !{i32 1}
2534
// CHECK: ![[NUM42]] = !{i32 42}
26-
35+
// CHECK: ![[NUM2]] = !{i32 2}

clang/test/SemaSYCL/num_simd_work_items.cpp renamed to clang/test/SemaSYCL/num_simd_work_items_device.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// RUN: %clang_cc1 %s -fsycl -fsycl-is-device -triple spir64 -fsyntax-only -Wno-sycl-2017-compat -DTRIGGER_ERROR -verify
22
// RUN: %clang_cc1 %s -fsycl -fsycl-is-device -triple spir64 -fsyntax-only -Wno-sycl-2017-compat -ast-dump | FileCheck %s
3-
// RUN: %clang_cc1 -fsycl -fsycl-is-host -fsyntax-only -Wno-sycl-2017-compat -verify %s
43

54
#ifndef __SYCL_DEVICE_ONLY__
65
struct FuncObj {
@@ -20,7 +19,6 @@ void foo() {
2019
}
2120

2221
#else // __SYCL_DEVICE_ONLY__
23-
2422
[[intelfpga::num_simd_work_items(2)]] void func_do_not_ignore() {}
2523

2624
struct FuncObj {
@@ -34,28 +32,31 @@ __attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) {
3432

3533
int main() {
3634
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel1
37-
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} 42
35+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
36+
// CHECK-NEXT: IntegerLiteral{{.*}}42{{$}}
3837
kernel<class test_kernel1>(
3938
FuncObj());
4039

4140
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel2
42-
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} 8
41+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
42+
// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
4343
kernel<class test_kernel2>(
4444
[]() [[intelfpga::num_simd_work_items(8)]] {});
4545

4646
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel3
47-
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} 2
47+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
48+
// CHECK-NEXT: IntegerLiteral{{.*}}2{{$}}
4849
kernel<class test_kernel3>(
4950
[]() { func_do_not_ignore(); });
5051

5152
#ifdef TRIGGER_ERROR
5253
[[intelfpga::num_simd_work_items(0)]] int Var = 0; // expected-error{{'num_simd_work_items' attribute only applies to functions}}
5354

5455
kernel<class test_kernel4>(
55-
[]() [[intelfpga::num_simd_work_items(0)]] {}); // expected-error{{'num_simd_work_items' attribute must be greater than 0}}
56+
[]() [[intelfpga::num_simd_work_items(0)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}
5657

5758
kernel<class test_kernel5>(
58-
[]() [[intelfpga::num_simd_work_items(-42)]] {}); // expected-error{{'num_simd_work_items' attribute requires a non-negative integral compile time constant expression}}
59+
[]() [[intelfpga::num_simd_work_items(-42)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}
5960

6061
kernel<class test_kernel6>(
6162
[]() [[intelfpga::num_simd_work_items(1), intelfpga::num_simd_work_items(2)]] {}); // expected-warning{{attribute 'num_simd_work_items' is already applied with different parameters}}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %clang_cc1 -fsycl -fsycl-is-host -fsyntax-only -Wno-sycl-2017-compat -verify %s
2+
// expected-no-diagnostics
3+
4+
[[intelfpga::num_simd_work_items(2)]] void func_do_not_ignore() {}
5+
6+
struct FuncObj {
7+
[[intelfpga::num_simd_work_items(42)]] void operator()() const {}
8+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s
2+
3+
// Test that checkes template parameter support for 'num_simd_work_items' attribute on sycl device.
4+
5+
template <int SIZE>
6+
class KernelFunctor {
7+
public:
8+
// expected-error@+1{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}
9+
[[intelfpga::num_simd_work_items(SIZE)]] void operator()() {}
10+
};
11+
12+
int main() {
13+
//expected-note@+1{{in instantiation of template class 'KernelFunctor<-1>' requested here}}
14+
KernelFunctor<-1>();
15+
// no error expected
16+
KernelFunctor<10>();
17+
}
18+
19+
// CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor
20+
// CHECK: ClassTemplateSpecializationDecl {{.*}} {{.*}} class KernelFunctor definition
21+
// CHECK: CXXRecordDecl {{.*}} {{.*}} implicit class KernelFunctor
22+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
23+
// CHECK: SubstNonTypeTemplateParmExpr {{.*}}
24+
// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}}
25+
// CHECK-NEXT: IntegerLiteral{{.*}}10{{$}}

0 commit comments

Comments
 (0)