Skip to content

Commit 73b7da0

Browse files
authored
[SYCL][FPGA] Add mutual diagnostic for num_simd_work_items attribute in conjunction with the reqd_work_group_size attribute (#3170)
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 implementation of the num_simd_work_items attribute. OpenCL spelling for num_simd_work_items attribute supports this rule. Current implementation of SYCL attribute “num_simd_work_items” and “reqd_work_group_size” does not support this. This patch 1. adds support for mutual diagnostic in sema for num_simd_work_items attribute interacting with reqd_work_group_size attribute. 2. adds tests 3. updates documentation about this new mutual diagnostic for num_simd_work_items attribute with the note and examples. Signed-off-by: Soumi Manna <soumi.manna@intel.com>
1 parent 47b85e5 commit 73b7da0

File tree

6 files changed

+457
-37
lines changed

6 files changed

+457
-37
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,26 @@ device kernel, the attribute is not ignored and it is propagated to the kernel.
24182418
[[intel::num_simd_work_items(N)]] void operator()() const {}
24192419
};
24202420

2421+
If the`` intel::reqd_work_group_size`` or ``cl::reqd_work_group_size``
2422+
attribute is specified on a declaration along with a
2423+
intel::num_simd_work_items attribute, the work group size attribute
2424+
arguments must all be evenly divisible by the argument specified in
2425+
the ``intel::num_simd_work_items`` attribute.
2426+
2427+
.. code-block:: c++
2428+
2429+
struct func {
2430+
[[intel::num_simd_work_items(4)]]
2431+
[[intel::reqd_work_group_size(64, 64, 64)]]
2432+
void operator()() const {}
2433+
};
2434+
2435+
struct bar {
2436+
[[intel::reqd_work_group_size(64, 64, 64)]]
2437+
[[intel::num_simd_work_items(4)]]
2438+
void operator()() const {}
2439+
};
2440+
24212441
}];
24222442
}
24232443

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11212,6 +11212,9 @@ def err_sycl_invalid_accessor_property_list_template_param : Error<
1121211212
"%select{accessor_property_list|accessor_property_list pack argument|buffer_location}0 "
1121311213
"template parameter must be a "
1121411214
"%select{parameter pack|type|non-negative integer}1">;
11215+
def err_sycl_num_kernel_wrong_reqd_wg_size : Error<
11216+
"%0 attribute must evenly divide the work-group size for the %1 attribute">;
11217+
1121511218
def warn_sycl_pass_by_value_deprecated
1121611219
: Warning<"Passing kernel functions by value is deprecated in SYCL 2020">,
1121711220
InGroup<Sycl2020Compat>, ShowInSystemHeader;

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13068,21 +13068,23 @@ void Sema::addIntelSingleArgAttr(Decl *D, const AttributeCommonInfo &CI,
1306813068
return;
1306913069
E = ICE.get();
1307013070
int32_t ArgInt = ArgVal.getSExtValue();
13071-
if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelNumSimdWorkItems ||
13072-
CI.getParsedKind() == ParsedAttr::AT_IntelReqdSubGroupSize ||
13071+
if (CI.getParsedKind() == ParsedAttr::AT_IntelReqdSubGroupSize ||
1307313072
CI.getParsedKind() == ParsedAttr::AT_IntelFPGAMaxReplicates) {
1307413073
if (ArgInt <= 0) {
1307513074
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1307613075
<< CI << /*positive*/ 0;
1307713076
return;
1307813077
}
1307913078
}
13080-
if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) {
13079+
if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim ||
13080+
CI.getParsedKind() == ParsedAttr::AT_SYCLIntelNumSimdWorkItems) {
1308113081
if (ArgInt < 0) {
1308213082
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
1308313083
<< CI << /*non-negative*/ 1;
1308413084
return;
1308513085
}
13086+
}
13087+
if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) {
1308613088
if (ArgInt > 3) {
1308713089
Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range)
1308813090
<< CI << 0 << 3 << E->getSourceRange();

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 84 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,26 +3130,53 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
31303130
return;
31313131
}
31323132

3133-
if (WorkGroupAttr *ExistingAttr = D->getAttr<WorkGroupAttr>()) {
3134-
ASTContext &Ctx = S.getASTContext();
3135-
Optional<llvm::APSInt> XDimVal = XDimExpr->getIntegerConstantExpr(Ctx);
3136-
Optional<llvm::APSInt> YDimVal = YDimExpr->getIntegerConstantExpr(Ctx);
3137-
Optional<llvm::APSInt> ZDimVal = ZDimExpr->getIntegerConstantExpr(Ctx);
3138-
Optional<llvm::APSInt> ExistingXDimVal = ExistingAttr->getXDimVal(Ctx);
3139-
Optional<llvm::APSInt> ExistingYDimVal = ExistingAttr->getYDimVal(Ctx);
3140-
Optional<llvm::APSInt> ExistingZDimVal = ExistingAttr->getZDimVal(Ctx);
3141-
3142-
// Compare attribute arguments value and warn for a mismatch.
3143-
if (ExistingXDimVal != XDimVal || ExistingYDimVal != YDimVal ||
3144-
ExistingZDimVal != ZDimVal) {
3145-
S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
3146-
S.Diag(ExistingAttr->getLocation(), diag::note_conflicting_attribute);
3133+
ASTContext &Ctx = S.getASTContext();
3134+
3135+
if (!XDimExpr->isValueDependent() && !YDimExpr->isValueDependent() &&
3136+
!ZDimExpr->isValueDependent()) {
3137+
llvm::APSInt XDimVal, YDimVal, ZDimVal;
3138+
ExprResult XDim = S.VerifyIntegerConstantExpression(XDimExpr, &XDimVal);
3139+
ExprResult YDim = S.VerifyIntegerConstantExpression(YDimExpr, &YDimVal);
3140+
ExprResult ZDim = S.VerifyIntegerConstantExpression(ZDimExpr, &ZDimVal);
3141+
3142+
if (XDim.isInvalid())
3143+
return;
3144+
XDimExpr = XDim.get();
3145+
3146+
if (YDim.isInvalid())
3147+
return;
3148+
YDimExpr = YDim.get();
3149+
3150+
if (ZDim.isInvalid())
3151+
return;
3152+
ZDimExpr = ZDim.get();
3153+
3154+
if (const auto *A = D->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
3155+
int64_t NumSimdWorkItems =
3156+
A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue();
3157+
3158+
if (!(XDimVal.getZExtValue() % NumSimdWorkItems == 0 ||
3159+
YDimVal.getZExtValue() % NumSimdWorkItems == 0 ||
3160+
ZDimVal.getZExtValue() % NumSimdWorkItems == 0)) {
3161+
S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size)
3162+
<< A << AL;
3163+
S.Diag(AL.getLoc(), diag::note_conflicting_attribute);
3164+
return;
3165+
}
3166+
}
3167+
if (const auto *ExistingAttr = D->getAttr<WorkGroupAttr>()) {
3168+
// Compare attribute arguments value and warn for a mismatch.
3169+
if (ExistingAttr->getXDimVal(Ctx) != XDimVal ||
3170+
ExistingAttr->getYDimVal(Ctx) != YDimVal ||
3171+
ExistingAttr->getZDimVal(Ctx) != ZDimVal) {
3172+
S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
3173+
S.Diag(ExistingAttr->getLocation(), diag::note_conflicting_attribute);
3174+
}
31473175
}
3176+
if (!checkWorkGroupSizeValues(S, D, AL))
3177+
return;
31483178
}
31493179

3150-
if (!checkWorkGroupSizeValues(S, D, AL))
3151-
return;
3152-
31533180
S.addIntelTripleArgAttr<WorkGroupAttr>(D, AL, XDimExpr, YDimExpr, ZDimExpr);
31543181
}
31553182

@@ -3196,18 +3223,51 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
31963223
}
31973224

31983225
// Handles num_simd_work_items.
3199-
static void handleNumSimdWorkItemsAttr(Sema &S, Decl *D, const ParsedAttr &A) {
3226+
static void handleNumSimdWorkItemsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
32003227
if (D->isInvalidDecl())
32013228
return;
32023229

3203-
Expr *E = A.getArgAsExpr(0);
3230+
Expr *E = AL.getArgAsExpr(0);
32043231

32053232
if (D->getAttr<SYCLIntelNumSimdWorkItemsAttr>())
3206-
S.Diag(A.getLoc(), diag::warn_duplicate_attribute) << A;
3233+
S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
32073234

3208-
S.CheckDeprecatedSYCLAttributeSpelling(A);
3235+
S.CheckDeprecatedSYCLAttributeSpelling(AL);
3236+
3237+
if (!E->isValueDependent()) {
3238+
llvm::APSInt ArgVal;
3239+
ExprResult ICE = S.VerifyIntegerConstantExpression(E, &ArgVal);
32093240

3210-
S.addIntelSingleArgAttr<SYCLIntelNumSimdWorkItemsAttr>(D, A, E);
3241+
if (ICE.isInvalid())
3242+
return;
3243+
3244+
E = ICE.get();
3245+
int64_t NumSimdWorkItems = ArgVal.getSExtValue();
3246+
3247+
if (NumSimdWorkItems == 0) {
3248+
S.Diag(E->getExprLoc(), diag::err_attribute_argument_is_zero)
3249+
<< AL << E->getSourceRange();
3250+
return;
3251+
}
3252+
3253+
if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
3254+
ASTContext &Ctx = S.getASTContext();
3255+
Optional<llvm::APSInt> XDimVal = A->getXDimVal(Ctx);
3256+
Optional<llvm::APSInt> YDimVal = A->getYDimVal(Ctx);
3257+
Optional<llvm::APSInt> ZDimVal = A->getZDimVal(Ctx);
3258+
3259+
if (!(XDimVal->getZExtValue() % NumSimdWorkItems == 0 ||
3260+
YDimVal->getZExtValue() % NumSimdWorkItems == 0 ||
3261+
ZDimVal->getZExtValue() % NumSimdWorkItems == 0)) {
3262+
S.Diag(AL.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size)
3263+
<< AL << A;
3264+
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
3265+
return;
3266+
}
3267+
}
3268+
}
3269+
3270+
S.addIntelSingleArgAttr<SYCLIntelNumSimdWorkItemsAttr>(D, AL, E);
32113271
}
32123272

32133273
// Handles use_stall_enable_clusters
@@ -5967,14 +6027,13 @@ void Sema::addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &Attr,
59676027
Optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(getASTContext());
59686028
if (!ArgVal) {
59696029
Diag(E->getExprLoc(), diag::err_attribute_argument_type)
5970-
<< Attr.getAttrName() << AANT_ArgumentIntegerConstant
5971-
<< E->getSourceRange();
6030+
<< Attr << AANT_ArgumentIntegerConstant << E->getSourceRange();
59726031
return;
59736032
}
59746033
int32_t ArgInt = ArgVal->getSExtValue();
59756034
if (ArgInt < 0) {
59766035
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
5977-
<< Attr.getAttrName() << /*non-negative*/ 1;
6036+
<< Attr << /*non-negative*/ 1;
59786037
return;
59796038
}
59806039
}

0 commit comments

Comments
 (0)