Skip to content

Commit b89e040

Browse files
committed
[SYCL] [FPGA] Add mutual diagnostic for num_simd_work_items attribute in conjunction with the reqd_work_group_size attribute
This is a follow up comments on intel#2906 (comment) There is a rule on FPGA document that the num_simd_work_items attribute we specify must evenly divide the work-group size we specify for the reqd_work_group_size attribute, was missed during initial implemention of the num_simd_work_items attribute. OpenCL spelling for num_simd_work_items attribute supports this rule. This patch 1. addes support for mutual diagnostic in Sema for num_simd_work_items attribute interacting with reqd_work_group_size attribute. 2. addes tests 3. updates documenation about the num_simd_work_items attribute with the note and exmaples. Current implementation of SYCL attribute “num_simd_work_items” and “reqd_work_group_size” does not support this. Signed-off-by: Soumi Manna <[email protected]>
1 parent ced4e34 commit b89e040

File tree

2 files changed

+173
-9
lines changed

2 files changed

+173
-9
lines changed

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,8 +3104,28 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
31043104
return;
31053105
}
31063106

3107+
ASTContext &Ctx = S.getASTContext();
3108+
3109+
if (AL.getKind() == ParsedAttr::AT_ReqdWorkGroupSize) {
3110+
if (const auto *A = D->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
3111+
Optional<llvm::APSInt> NumSimdWorkItems =
3112+
A->getValue()->getIntegerConstantExpr(Ctx);
3113+
Optional<llvm::APSInt> XDimVal = XDimExpr->getIntegerConstantExpr(Ctx);
3114+
Optional<llvm::APSInt> YDimVal = YDimExpr->getIntegerConstantExpr(Ctx);
3115+
Optional<llvm::APSInt> ZDimVal = ZDimExpr->getIntegerConstantExpr(Ctx);
3116+
3117+
if (!(XDimVal->getExtValue() % NumSimdWorkItems->getExtValue() == 0 ||
3118+
YDimVal->getZExtValue() % NumSimdWorkItems->getExtValue() == 0 ||
3119+
ZDimVal->getZExtValue() % NumSimdWorkItems->getExtValue() == 0)) {
3120+
S.Diag(A->getLocation(), diag::err_conflicting_sycl_function_attributes)
3121+
<< A << AL;
3122+
S.Diag(AL.getLoc(), diag::note_conflicting_attribute);
3123+
return;
3124+
}
3125+
}
3126+
}
3127+
31073128
if (WorkGroupAttr *ExistingAttr = D->getAttr<WorkGroupAttr>()) {
3108-
ASTContext &Ctx = S.getASTContext();
31093129
Optional<llvm::APSInt> XDimVal = XDimExpr->getIntegerConstantExpr(Ctx);
31103130
Optional<llvm::APSInt> YDimVal = YDimExpr->getIntegerConstantExpr(Ctx);
31113131
Optional<llvm::APSInt> ZDimVal = ZDimExpr->getIntegerConstantExpr(Ctx);
@@ -3171,18 +3191,38 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
31713191
}
31723192

31733193
// Handles num_simd_work_items.
3174-
static void handleNumSimdWorkItemsAttr(Sema &S, Decl *D, const ParsedAttr &A) {
3194+
static void handleNumSimdWorkItemsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
31753195
if (D->isInvalidDecl())
31763196
return;
31773197

3178-
Expr *E = A.getArgAsExpr(0);
3198+
Expr *E = AL.getArgAsExpr(0);
31793199

31803200
if (D->getAttr<SYCLIntelNumSimdWorkItemsAttr>())
3181-
S.Diag(A.getLoc(), diag::warn_duplicate_attribute) << A;
3201+
S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
31823202

3183-
S.CheckDeprecatedSYCLAttributeSpelling(A);
3203+
S.CheckDeprecatedSYCLAttributeSpelling(AL);
3204+
3205+
if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
3206+
ASTContext &Ctx = S.getASTContext();
3207+
3208+
if (!E->isValueDependent()) {
3209+
Optional<llvm::APSInt> NumSimdWorkItems = E->getIntegerConstantExpr(Ctx);
3210+
Optional<llvm::APSInt> XDimVal = A->getXDimVal(Ctx);
3211+
Optional<llvm::APSInt> YDimVal = A->getYDimVal(Ctx);
3212+
Optional<llvm::APSInt> ZDimVal = A->getZDimVal(Ctx);
3213+
3214+
if (!(XDimVal->getExtValue() % NumSimdWorkItems->getExtValue() == 0 ||
3215+
YDimVal->getZExtValue() % NumSimdWorkItems->getExtValue() == 0 ||
3216+
ZDimVal->getZExtValue() % NumSimdWorkItems->getExtValue() == 0)) {
3217+
S.Diag(AL.getLoc(), diag::err_conflicting_sycl_function_attributes)
3218+
<< AL << A->getSpelling();
3219+
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
3220+
return;
3221+
}
3222+
}
3223+
}
31843224

3185-
S.addIntelSYCLSingleArgFunctionAttr<SYCLIntelNumSimdWorkItemsAttr>(D, A, E);
3225+
S.addIntelSYCLSingleArgFunctionAttr<SYCLIntelNumSimdWorkItemsAttr>(D, AL, E);
31863226
}
31873227

31883228
// Handles use_stall_enable_clusters

clang/test/SemaSYCL/num_simd_work_items_device.cpp

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,68 @@ struct FuncObj {
3333
[[intel::num_simd_work_items(42)]] void operator()() const {}
3434
};
3535

36+
#ifdef TRIGGER_ERROR
37+
struct TRIFuncObjBad1 {
38+
[[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute conflicts with ''reqd_work_group_size'' attribute}}
39+
[[intel::reqd_work_group_size(5, 5, 5)]] //expected-note{{conflicting attribute is here}}
40+
void operator()() const {}
41+
};
42+
43+
struct TRIFuncObjBad2 {
44+
[[intel::reqd_work_group_size(5, 5, 5)]] // expected-note{{conflicting attribute is here}}
45+
[[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute conflicts with 'reqd_work_group_size' attribute}}
46+
void operator()() const {}
47+
};
48+
49+
struct TRIFuncObjBad3 {
50+
[[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute conflicts with ''reqd_work_group_size'' attribute}}
51+
[[cl::reqd_work_group_size(5, 5, 5)]] //expected-note{{conflicting attribute is here}}
52+
void operator()() const {}
53+
};
54+
55+
struct TRIFuncObjBad4 {
56+
[[cl::reqd_work_group_size(5, 5, 5)]] // expected-note{{conflicting attribute is here}}
57+
[[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute conflicts with 'reqd_work_group_size' attribute}}
58+
void operator()() const {}
59+
};
60+
#endif // TRIGGER_ERROR
61+
62+
struct TRIFuncObjGood1 {
63+
[[intel::num_simd_work_items(4)]] //OK
64+
[[intel::reqd_work_group_size(64, 64, 64)]]
65+
void operator()() const {}
66+
};
67+
68+
struct TRIFuncObjGood2 {
69+
[[intel::reqd_work_group_size(64, 64, 64)]]
70+
[[intel::num_simd_work_items(4)]] //OK
71+
void operator()() const {}
72+
};
73+
74+
struct TRIFuncObjGood3 {
75+
[[intel::num_simd_work_items(4)]] //OK
76+
[[cl::reqd_work_group_size(64, 64, 64)]]
77+
void operator()() const {}
78+
};
79+
80+
struct TRIFuncObjGood4 {
81+
[[cl::reqd_work_group_size(64, 64, 64)]]
82+
[[intel::num_simd_work_items(4)]] //OK
83+
void operator()() const {}
84+
};
85+
86+
struct TRIFuncObjGood5 {
87+
[[intel::num_simd_work_items(3)]] //OK
88+
[[intel::max_work_group_size(5, 5, 5)]]
89+
void operator()() const {}
90+
};
91+
92+
struct TRIFuncObjGood6 {
93+
[[intel::max_work_group_size(5, 5, 5)]]
94+
[[intel::num_simd_work_items(3)]] //OK
95+
void operator()() const {}
96+
};
97+
3698
int main() {
3799
q.submit([&](handler &h) {
38100
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel1
@@ -54,16 +116,78 @@ int main() {
54116
h.single_task<class test_kernel3>(
55117
[]() { func_do_not_ignore(); });
56118

119+
h.single_task<class test_kernel4>(TRIFuncObjGood1());
120+
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel4
121+
// CHECK: ReqdWorkGroupSizeAttr {{.*}}
122+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
123+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
124+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
125+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
126+
// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
127+
128+
h.single_task<class test_kernel5>(TRIFuncObjGood2());
129+
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel5
130+
// CHECK: ReqdWorkGroupSizeAttr {{.*}}
131+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
132+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
133+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
134+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
135+
// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
136+
137+
h.single_task<class test_kernel6>(TRIFuncObjGood3());
138+
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel6
139+
// CHECK: ReqdWorkGroupSizeAttr {{.*}}
140+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
141+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
142+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
143+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
144+
// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
145+
146+
h.single_task<class test_kernel7>(TRIFuncObjGood4());
147+
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel7
148+
// CHECK: ReqdWorkGroupSizeAttr {{.*}}
149+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
150+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
151+
// CHECK-NEXT: IntegerLiteral{{.*}}64{{$}}
152+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
153+
// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
154+
155+
h.single_task<class test_kernel8>(TRIFuncObjGood5());
156+
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel8
157+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
158+
// CHECK-NEXT: IntegerLiteral{{.*}}3{{$}}
159+
// CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}}
160+
// CHECK-NEXT: IntegerLiteral{{.*}}5{{$}}
161+
// CHECK-NEXT: IntegerLiteral{{.*}}5{{$}}
162+
// CHECK-NEXT: IntegerLiteral{{.*}}5{{$}}
163+
164+
h.single_task<class test_kernel9>(TRIFuncObjGood6());
165+
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel9
166+
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
167+
// CHECK-NEXT: IntegerLiteral{{.*}}3{{$}}
168+
// CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}}
169+
// CHECK-NEXT: IntegerLiteral{{.*}}5{{$}}
170+
// CHECK-NEXT: IntegerLiteral{{.*}}5{{$}}
171+
// CHECK-NEXT: IntegerLiteral{{.*}}5{{$}}
172+
57173
#ifdef TRIGGER_ERROR
58174
[[intel::num_simd_work_items(0)]] int Var = 0; // expected-error{{'num_simd_work_items' attribute only applies to functions}}
59175

60-
h.single_task<class test_kernel4>(
176+
h.single_task<class test_kernel10>(
61177
[]() [[intel::num_simd_work_items(0)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}
62178

63-
h.single_task<class test_kernel5>(
179+
h.single_task<class test_kernel11>(
64180
[]() [[intel::num_simd_work_items(-42)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}
65181

66-
h.single_task<class test_kernel6>(
182+
h.single_task<class test_kernel12>(TRIFuncObjBad1());
183+
184+
h.single_task<class test_kernel13>(TRIFuncObjBad2());
185+
186+
h.single_task<class test_kernel14>(TRIFuncObjBad3());
187+
188+
h.single_task<class test_kernel15>(TRIFuncObjBad4());
189+
190+
h.single_task<class test_kernel16>(
67191
[]() [[intel::num_simd_work_items(1), intel::num_simd_work_items(2)]]{}); // expected-warning{{attribute 'num_simd_work_items' is already applied with different parameters}}
68192
#endif // TRIGGER_ERROR
69193
});

0 commit comments

Comments
 (0)