From 68f33f2c73fcefb5532a964eb3151140a4b193b1 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 15:07:41 -0700 Subject: [PATCH 01/20] Fix Bug Signed-off-by: Soumi Manna --- clang/include/clang/Basic/Attr.td | 3 + clang/include/clang/Basic/AttrDocs.td | 71 ++++-- clang/lib/Sema/SemaDeclAttr.cpp | 39 ++- .../SemaSYCL/num_simd_work_items_device.cpp | 230 +++++++----------- 4 files changed, 170 insertions(+), 173 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index a05fe355d314d..9f4b3833aeffc 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2944,6 +2944,9 @@ def ReqdWorkGroupSize : InheritableAttr { ExprArgument<"YDim", /*optional*/1>, ExprArgument<"ZDim", /*optional*/1>]; let Subjects = SubjectList<[Function], ErrorDiag>; + let Accessors = [Accessor<"usesOpenCLArgOrdering", + [GNU<"reqd_work_group_size">, + CXX11<"cl","reqd_work_group_size">]>]; let AdditionalMembers = [{ ArrayRef dimensions() const { return {getXDim(), getYDim(), getZDim()}; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 6e033f9e083b2..ac7de6c221049 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2503,26 +2503,6 @@ device kernel, the attribute is not ignored and it is propagated to the kernel. [[intel::num_simd_work_items(N)]] void operator()() const {} }; -If the`` intel::reqd_work_group_size`` or ``cl::reqd_work_group_size`` -attribute is specified on a declaration along with a -intel::num_simd_work_items attribute, the work group size attribute -argument (the first argument) must be evenly divisible by the argument specified -in the ``intel::num_simd_work_items`` attribute. - -.. code-block:: c++ - - struct func { - [[intel::num_simd_work_items(4)]] - [[intel::reqd_work_group_size(64, 64, 64)]] - void operator()() const {} - }; - - struct bar { - [[intel::reqd_work_group_size(64, 64, 64)]] - [[intel::num_simd_work_items(4)]] - void operator()() const {} - }; - }]; } @@ -2636,6 +2616,57 @@ In OpenCL C, this attribute is available in GNU spelling __kernel __attribute__((reqd_work_group_size(8, 16, 32))) void test() {} +The order of the arguments to reqd_work_group_size in SYCL and OpenCL are +reversed. In the OpenCL syntax, ``[[cl::reqd_work_group_size(X, Y, Z)]]`` or +(``__attribute__((reqd_work_group_size(X, Y, Z)))``), X is the index that +increments the fastest, followed by Y, then Z. If we preserve that definition +of X, Y, and Z, then in SYCL the attribute is specified as +``[[intel::reqd_work_group_size(Z, Y, X)]]``. This gets more complicated in the +case where fewer than three arguments are provided since this spelling allows +the Y and Z arguments to be optional. In such a case it's not the ``X`` argument +that is omitted (by the definitions of X, Y, and Z above) it's the ``Z`` +dimension that's omitted. So the two argument version has the syntax +``[[intel::reqd_work_group_size(Y, X)]]``. Similarly, the one argument variant +has syntax ``[[intel::reqd_work_group_size(X)]]``. +In summary, in SYCL if the ``intel::reqd_work_group_size`` attribute is +specified on a declaration along with a ``intel::num_simd_work_items`` +attribute, the work group size (the last argument) must be evenly divisible by +the argument specified in the ``intel::num_simd_work_items``regardless of how +many arguments req_work_group_size has. + +.. code-block:: c++ + + struct func { + [[intel::num_simd_work_items(4)]] + [[intel::reqd_work_group_size(3, 4, 64)]] + void operator()() const {} + }; + + struct bar { + [[intel::reqd_work_group_size(3, 4, 64)]] + [[intel::num_simd_work_items(4)]] + void operator()() const {} + }; + +If the ``cl::reqd_work_group_size`` or ``__attribute__((reqd_work_group_size()))`` +attribute is specified on a declaration along with a ``intel::num_simd_work_items`` +attribute, the work group size (the first argument) must be evenly divisible by +the argument specified in the ``intel::num_simd_work_items`` attribute. +GNU and ``cl::reqd_work_group_size`` spelling of ReqdWorkGroupSizeAttr maps to +the OpenCL semantic. The first and last argument are only swapped for the Intel +attributes in SYCL and not the OpenCL ones. + +.. code-block:: c++ + + struct func1 { + [[intel::num_simd_work_items(4)]] + [[cl::reqd_work_group_size(64, 4, 3)]] + void operator()() const {} + }; + + [[intel::num_simd_work_items(2)]] + __attribute__((reqd_work_group_size(4, 2, 3))) void bar(); + }]; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 548fa364d08d9..e28e6fbbe49ff 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3086,17 +3086,35 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { return; ZDimExpr = ZDim.get(); + // If the declaration has an [[intel::num_simd_work_items()]] attribute, + // check to see if the first argument of [[cl::reqd_work_group_size()]] + // or __attribute__((reqd_work_group_size)) attribute and last argument + // of [intel::reqd_work_group_size()]] attribute can be evenly divided by + // the num_simd_work_items attribute. GNU and [[cl::reqd_work_group_size]] + // spelling of ReqdWorkGroupSizeAttr maps to the OpenCL + // semantics. First and last argument are only swapped for the Intel + // atributes in SYCL and not the OpenCL ones. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); - if (XDimVal.getZExtValue() % NumSimdWorkItems != 0) { + bool UsesOpenCLArgOrdering = + ((AL.getSyntax() == AttributeCommonInfo::AS_CXX11 || + AL.getSyntax() == AttributeCommonInfo::AS_C2x) && + AL.hasScope() && AL.getScopeName()->isStr("cl")) || + AL.getSyntax() == AttributeCommonInfo::AS_GNU; + + unsigned WorkGroupSize = UsesOpenCLArgOrdering ? XDimVal.getZExtValue() + : ZDimVal.getZExtValue(); + + if (WorkGroupSize % NumSimdWorkItems != 0) { S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) << A << AL; S.Diag(AL.getLoc(), diag::note_conflicting_attribute); return; } } + if (const auto *ExistingAttr = D->getAttr()) { // Compare attribute arguments value and warn for a mismatch. if (ExistingAttr->getXDimVal(Ctx) != XDimVal || @@ -3280,13 +3298,24 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, } } - // If the declaration has an [[intel::reqd_work_group_size]] attribute, - // check to see if the first argument can be evenly divided by the - // num_simd_work_items attribute. + // If the declaration has a [[intel::reqd_work_group_size()]] + // attribute, check to see if the last argument can be evenly + // divided by the num_simd_work_items attribute. + // If the declaration has a __attribute__((reqd_work_group_size)) + // or [[cl::reqd_work_group_size()]] attribute, check to see if the + // first argument can be evenly divided by the num_simd_work_items + // attribute. GNU and [[cl::reqd_work_group_size()]] spelling of + // ReqdWorkGroupSizeAttr maps to the OpenCL semantics. First and last + // argument are only swapped for the Intel atributes in SYCL and not + // the OpenCL ones. if (const auto *DeclAttr = D->getAttr()) { Optional XDimVal = DeclAttr->getXDimVal(Context); + Optional ZDimVal = DeclAttr->getZDimVal(Context); + + llvm::APSInt WorkGroupSize = + DeclAttr->usesOpenCLArgOrdering() ? *XDimVal : *ZDimVal; - if (*XDimVal % ArgVal != 0) { + if (WorkGroupSize % ArgVal != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) << CI << DeclAttr; Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute); diff --git a/clang/test/SemaSYCL/num_simd_work_items_device.cpp b/clang/test/SemaSYCL/num_simd_work_items_device.cpp index c0a378a34c04c..0a4624b8a48ad 100644 --- a/clang/test/SemaSYCL/num_simd_work_items_device.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items_device.cpp @@ -42,66 +42,83 @@ struct FuncObj { }; #ifdef TRIGGER_ERROR -// If the declaration has an [[intel::reqd_work_group_size]] or -// [[cl::reqd_work_group_size]] attribute, tests that check if -// the work group size attribute argument (the first argument) -// can be evenly divided by the num_simd_work_items attribute. +// If the declaration has a [[intel::reqd_work_group_size]] +// attribute, tests that check if the work group size attribute +// argument (the last argument) can be evenly divided by the +// num_simd_work_items attribute. struct TRIFuncObjBad1 { [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} - [[intel::reqd_work_group_size(5, 3, 3)]] // expected-note{{conflicting attribute is here}} + [[intel::reqd_work_group_size(3, 6, 5)]] // expected-note{{conflicting attribute is here}} void operator()() const {} }; struct TRIFuncObjBad2 { - [[intel::reqd_work_group_size(5, 3, 3)]] // expected-note{{conflicting attribute is here}} + [[intel::reqd_work_group_size(3, 6, 5)]] // expected-note{{conflicting attribute is here}} [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} void operator()() const {} }; struct TRIFuncObjBad3 { - [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} - [[cl::reqd_work_group_size(5, 3, 3)]] // expected-note{{conflicting attribute is here}} + [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[intel::reqd_work_group_size(3)]] //expected-note{{conflicting attribute is here}} void operator()() const {} }; struct TRIFuncObjBad4 { - [[cl::reqd_work_group_size(5, 3, 3)]] // expected-note{{conflicting attribute is here}} - [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[intel::reqd_work_group_size(3)]] // expected-note{{conflicting attribute is here}} + [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} void operator()() const {} }; struct TRIFuncObjBad5 { - [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} - [[intel::reqd_work_group_size(5)]] //expected-note{{conflicting attribute is here}} + [[intel::num_simd_work_items(4)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[intel::reqd_work_group_size(4, 64)]] // expected-note{{conflicting attribute is here}} void operator()() const {} }; struct TRIFuncObjBad6 { - [[intel::reqd_work_group_size(5)]] // expected-note{{conflicting attribute is here}} - [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[intel::reqd_work_group_size(4, 64)]] // expected-note{{conflicting attribute is here}} + [[intel::num_simd_work_items(4)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} void operator()() const {} }; +[[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} +[[intel::reqd_work_group_size(4, 2, 3)]] void func1(); // expected-note{{conflicting attribute is here}} + +// If the declaration has a [[cl::reqd_work_group_size]] +// or __attribute__((reqd_work_group_size())) attribute, +// tests that check if the work group size attribute argument +// (the first argument) can be evenly divided by the num_simd_work_items +// attribute. GNU and [[cl::reqd_work_group_size]] spelling of +// ReqdWorkGroupSizeAttr maps to the OpenCL semantics. +// First and last argument are only swapped for the Intel atributes in +// SYCL and not the OpenCL ones. struct TRIFuncObjBad7 { - [[intel::num_simd_work_items(4)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} - [[intel::reqd_work_group_size(3, 64)]] // expected-note{{conflicting attribute is here}} + [[cl::reqd_work_group_size(5, 6, 8)]] // expected-note{{conflicting attribute is here}} + [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} void operator()() const {} }; struct TRIFuncObjBad8 { - [[intel::reqd_work_group_size(3, 64)]] // expected-note{{conflicting attribute is here}} - [[intel::num_simd_work_items(4)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[cl::reqd_work_group_size(5, 6, 8)]] // expected-note{{conflicting attribute is here}} void operator()() const {} }; +[[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} +__attribute__((reqd_work_group_size(3, 2, 4))) void func2(); // expected-note{{conflicting attribute is here}} + +[[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} +[[cl::reqd_work_group_size(5, 2, 4)]] void func3(); // expected-note{{conflicting attribute is here}} + // Tests for incorrect argument values for Intel FPGA num_simd_work_items and reqd_work_group_size function attributes struct TRIFuncObjBad9 { [[intel::reqd_work_group_size(5, 5, 5)]] @@ -164,57 +181,42 @@ struct TRIFuncObjBad18 { }; #endif // TRIGGER_ERROR -// If the declaration has an [[intel::reqd_work_group_size]] or -// [[cl::reqd_work_group_size]] attribute, tests that check if -// the work group size attribute argument (the first argument) -// can be evenly divided by the num_simd_work_items attribute. +// If the declaration has a [[intel::reqd_work_group_size()]] +// attribute, check to see if the last argument can be evenly +// divided by the num_simd_work_items attribute. +// If the declaration has a __attribute__((reqd_work_group_size)) +// or [[cl::reqd_work_group_size()]] attribute, check to see if the +// first argument can be evenly divided by the num_simd_work_items +// attribute. GNU and [[cl::reqd_work_group_size()]] spelling of +// ReqdWorkGroupSizeAttr maps to the OpenCL semantics. First and last +// argument are only swapped for the Intel atributes in SYCL and not +// the OpenCL ones. struct TRIFuncObjGood1 { [[intel::num_simd_work_items(4)]] - [[intel::reqd_work_group_size(64, 64, 5)]] void + [[intel::reqd_work_group_size(3, 64, 4)]] void operator()() const {} }; struct TRIFuncObjGood2 { - [[intel::reqd_work_group_size(64, 64, 5)]] + [[intel::reqd_work_group_size(3, 64, 4)]] [[intel::num_simd_work_items(4)]] void operator()() const {} }; struct TRIFuncObjGood3 { [[intel::num_simd_work_items(4)]] - [[cl::reqd_work_group_size(64, 64, 5)]] void + [[cl::reqd_work_group_size(4, 64, 5)]] void operator()() const {} }; struct TRIFuncObjGood4 { - [[cl::reqd_work_group_size(64, 64, 5)]] + [[cl::reqd_work_group_size(4, 64, 5)]] [[intel::num_simd_work_items(4)]] void operator()() const {} }; -struct TRIFuncObjGood5 { - [[intel::num_simd_work_items(4)]] - [[intel::reqd_work_group_size(64)]] void - operator()() const {} -}; - -struct TRIFuncObjGood6 { - [[intel::reqd_work_group_size(64)]] - [[intel::num_simd_work_items(4)]] void - operator()() const {} -}; - -struct TRIFuncObjGood7 { - [[intel::num_simd_work_items(4)]] - [[intel::reqd_work_group_size(64, 5)]] void - operator()() const {} -}; - -struct TRIFuncObjGood8 { - [[intel::reqd_work_group_size(64, 5)]] - [[intel::num_simd_work_items(4)]] void - operator()() const {} -}; +[[intel::num_simd_work_items(2)]] +__attribute__((reqd_work_group_size(4,3,3))) void func4(); //OK int main() { q.submit([&](handler &h) { @@ -251,27 +253,27 @@ int main() { // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK: ReqdWorkGroupSizeAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} + // CHECK-NEXT: value: Int 3 + // CHECK-NEXT: IntegerLiteral{{.*}}3{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 64 // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 5 - // CHECK-NEXT: IntegerLiteral{{.*}}5{{$}} + // CHECK-NEXT: value: Int 4 + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} h.single_task(TRIFuncObjGood2()); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel5 // CHECK: ReqdWorkGroupSizeAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} + // CHECK-NEXT: value: Int 3 + // CHECK-NEXT: IntegerLiteral{{.*}}3{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 64 // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 5 - // CHECK-NEXT: IntegerLiteral{{.*}}5{{$}} + // CHECK-NEXT: value: Int 4 + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 4 @@ -285,8 +287,8 @@ int main() { // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK: ReqdWorkGroupSizeAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} + // CHECK-NEXT: value: Int 4 + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 64 // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} @@ -298,82 +300,14 @@ int main() { // CHECK-LABEL: FunctionDecl {{.*}}test_kernel7 // CHECK: ReqdWorkGroupSizeAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 5 - // CHECK-NEXT: IntegerLiteral{{.*}}5{{$}} - // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 4 - // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} - - h.single_task(TRIFuncObjGood5()); - // CHECK-LABEL: FunctionDecl {{.*}}test_kernel8 - // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 4 - // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} - // CHECK: ReqdWorkGroupSizeAttr {{.*}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 1 - // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 1 - // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} - - h.single_task(TRIFuncObjGood6()); - // CHECK-LABEL: FunctionDecl {{.*}}test_kernel9 - // CHECK: ReqdWorkGroupSizeAttr {{.*}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 1 - // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 1 - // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} - // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 4 - // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} - - h.single_task(TRIFuncObjGood7()); - // CHECK-LABEL: FunctionDecl {{.*}}test_kernel10 - // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 4 // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} - // CHECK: ReqdWorkGroupSizeAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 64 // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 5 // CHECK-NEXT: IntegerLiteral{{.*}}5{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 1 - // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} - - h.single_task(TRIFuncObjGood8()); - // CHECK-LABEL: FunctionDecl {{.*}}test_kernel11 - // CHECK: ReqdWorkGroupSizeAttr {{.*}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 64 - // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 5 - // CHECK-NEXT: IntegerLiteral{{.*}}5{{$}} - // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 1 - // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 4 @@ -382,49 +316,49 @@ int main() { #ifdef TRIGGER_ERROR [[intel::num_simd_work_items(0)]] int Var = 0; // expected-error{{'num_simd_work_items' attribute only applies to functions}} - h.single_task( + h.single_task( []() [[intel::num_simd_work_items(0)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} - h.single_task( + h.single_task( []() [[intel::num_simd_work_items(-42)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} - h.single_task(TRIFuncObjBad1()); + h.single_task(TRIFuncObjBad1()); - h.single_task(TRIFuncObjBad2()); + h.single_task(TRIFuncObjBad2()); - h.single_task(TRIFuncObjBad3()); + h.single_task(TRIFuncObjBad3()); - h.single_task(TRIFuncObjBad4()); + h.single_task(TRIFuncObjBad4()); - h.single_task(TRIFuncObjBad5()); + h.single_task(TRIFuncObjBad5()); - h.single_task(TRIFuncObjBad6()); + h.single_task(TRIFuncObjBad6()); - h.single_task(TRIFuncObjBad7()); + h.single_task(TRIFuncObjBad7()); - h.single_task(TRIFuncObjBad8()); + h.single_task(TRIFuncObjBad8()); - h.single_task(TRIFuncObjBad9()); + h.single_task(TRIFuncObjBad9()); - h.single_task(TRIFuncObjBad10()); + h.single_task(TRIFuncObjBad10()); - h.single_task(TRIFuncObjBad11()); + h.single_task(TRIFuncObjBad11()); - h.single_task(TRIFuncObjBad12()); + h.single_task(TRIFuncObjBad12()); - h.single_task(TRIFuncObjBad13()); + h.single_task(TRIFuncObjBad13()); - h.single_task(TRIFuncObjBad14()); + h.single_task(TRIFuncObjBad14()); - h.single_task(TRIFuncObjBad15()); + h.single_task(TRIFuncObjBad15()); - h.single_task(TRIFuncObjBad16()); + h.single_task(TRIFuncObjBad16()); - h.single_task(TRIFuncObjBad17()); + h.single_task(TRIFuncObjBad17()); - h.single_task(TRIFuncObjBad18()); + h.single_task(TRIFuncObjBad18()); - h.single_task( + h.single_task( []() [[intel::num_simd_work_items(1), intel::num_simd_work_items(2)]]{}); // expected-warning{{attribute 'num_simd_work_items' is already applied with different arguments}} \ // expected-note {{previous attribute is here}} #endif // TRIGGER_ERROR From 704696a0ac0217bec44f3b93fa0ee5fdd7d64d78 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 15:13:53 -0700 Subject: [PATCH 02/20] Fix clang format issues Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e28e6fbbe49ff..a17c0a85b3ad3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3313,7 +3313,7 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, Optional ZDimVal = DeclAttr->getZDimVal(Context); llvm::APSInt WorkGroupSize = - DeclAttr->usesOpenCLArgOrdering() ? *XDimVal : *ZDimVal; + DeclAttr->usesOpenCLArgOrdering() ? *XDimVal : *ZDimVal; if (WorkGroupSize % ArgVal != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) From a58fa56ef159c0f498fc0b6123d54657c0ced0bd Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 19:26:42 -0700 Subject: [PATCH 03/20] Update patch Signed-off-by: Soumi Manna --- clang/include/clang/Basic/Attr.td | 3 +- clang/include/clang/Basic/AttrDocs.td | 54 +++++++----- clang/lib/Sema/SemaDeclAttr.cpp | 39 ++++----- .../SemaSYCL/num_simd_work_items_device.cpp | 83 ++++++++++--------- 4 files changed, 97 insertions(+), 82 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 9f4b3833aeffc..93988b0ec3a8e 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2945,8 +2945,7 @@ def ReqdWorkGroupSize : InheritableAttr { ExprArgument<"ZDim", /*optional*/1>]; let Subjects = SubjectList<[Function], ErrorDiag>; let Accessors = [Accessor<"usesOpenCLArgOrdering", - [GNU<"reqd_work_group_size">, - CXX11<"cl","reqd_work_group_size">]>]; + [GNU<"reqd_work_group_size">]>]; let AdditionalMembers = [{ ArrayRef dimensions() const { return {getXDim(), getYDim(), getZDim()}; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index ac7de6c221049..b59872c92d49a 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2617,22 +2617,27 @@ In OpenCL C, this attribute is available in GNU spelling __kernel __attribute__((reqd_work_group_size(8, 16, 32))) void test() {} The order of the arguments to reqd_work_group_size in SYCL and OpenCL are -reversed. In the OpenCL syntax, ``[[cl::reqd_work_group_size(X, Y, Z)]]`` or +reversed. In the OpenCL syntax, (``__attribute__((reqd_work_group_size(X, Y, Z)))``), X is the index that increments the fastest, followed by Y, then Z. If we preserve that definition of X, Y, and Z, then in SYCL the attribute is specified as -``[[intel::reqd_work_group_size(Z, Y, X)]]``. This gets more complicated in the -case where fewer than three arguments are provided since this spelling allows +``[[intel::reqd_work_group_size(Z, Y, X)]]`` or +``[[cl::reqd_work_group_size(Z, Y, X)]]``. This gets more complicated in the +case where fewer than three arguments are provided since +``[[intel::reqd_work_group_size(Z, Y, X)]]`` attribute spelling allows the Y and Z arguments to be optional. In such a case it's not the ``X`` argument that is omitted (by the definitions of X, Y, and Z above) it's the ``Z`` dimension that's omitted. So the two argument version has the syntax ``[[intel::reqd_work_group_size(Y, X)]]``. Similarly, the one argument variant has syntax ``[[intel::reqd_work_group_size(X)]]``. -In summary, in SYCL if the ``intel::reqd_work_group_size`` attribute is -specified on a declaration along with a ``intel::num_simd_work_items`` -attribute, the work group size (the last argument) must be evenly divisible by -the argument specified in the ``intel::num_simd_work_items``regardless of how -many arguments req_work_group_size has. +In summary, in SYCL if the ``intel::reqd_work_group_size`` or +``cl::reqd_work_group_size`` attribute is specified on a declaration along with +a ``intel::num_simd_work_items`` attribute, the required work-group size +(``X`` dimention, which is the last dimension in the reqd_work_group_size) must +be evenly divisible by the argument specified in the +``intel::num_simd_work_items``. +Fore more information, see the documentation about required work-group size. +..`Specify a Work-Group Size`: https://software.intel.com/content/www/us/en/develop/documentation/oneapi-fpga-optimization-guide/top/optimize-your-design/resource-use/specify-a-work-group-size.html .. code-block:: c++ @@ -2648,25 +2653,34 @@ many arguments req_work_group_size has. void operator()() const {} }; -If the ``cl::reqd_work_group_size`` or ``__attribute__((reqd_work_group_size()))`` -attribute is specified on a declaration along with a ``intel::num_simd_work_items`` -attribute, the work group size (the first argument) must be evenly divisible by -the argument specified in the ``intel::num_simd_work_items`` attribute. -GNU and ``cl::reqd_work_group_size`` spelling of ReqdWorkGroupSizeAttr maps to -the OpenCL semantic. The first and last argument are only swapped for the Intel -attributes in SYCL and not the OpenCL ones. - -.. code-block:: c++ - struct func1 { [[intel::num_simd_work_items(4)]] - [[cl::reqd_work_group_size(64, 4, 3)]] + [[cl::reqd_work_group_size(3, 4, 64)]] void operator()() const {} }; + + struct bar1 { + [[cl::reqd_work_group_size(3, 4, 64)]] + [[intel::num_simd_work_items(4)]] + void operator()() const {} + }; + +If the ``__attribute__((reqd_work_group_size()))`` attribute is specified on +a declaration along with a ``intel::num_simd_work_items`` +attribute, the required work-group size (``X`` dimention, which is the first +dimension in the reqd_work_group_size) must be evenly divisible by +the argument specified in the ``intel::num_simd_work_items`` attribute. +GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantic. The first and +last dimension are only swapped for the attributes in SYCL and not the OpenCL ones. + +.. code-block:: c++ [[intel::num_simd_work_items(2)]] - __attribute__((reqd_work_group_size(4, 2, 3))) void bar(); + __attribute__((reqd_work_group_size(4, 2, 3))) void test(); + __attribute__((reqd_work_group_size(4, 2, 3))) + [[intel::num_simd_work_items(2)]] void test1(); + }]; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a17c0a85b3ad3..f2d120bd62aea 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3087,21 +3087,17 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { ZDimExpr = ZDim.get(); // If the declaration has an [[intel::num_simd_work_items()]] attribute, - // check to see if the first argument of [[cl::reqd_work_group_size()]] - // or __attribute__((reqd_work_group_size)) attribute and last argument - // of [intel::reqd_work_group_size()]] attribute can be evenly divided by - // the num_simd_work_items attribute. GNU and [[cl::reqd_work_group_size]] - // spelling of ReqdWorkGroupSizeAttr maps to the OpenCL - // semantics. First and last argument are only swapped for the Intel - // atributes in SYCL and not the OpenCL ones. + // check to see if the first argument of __attribute__((reqd_work_group_size)) + // attribute and last argument of [[cl::reqd_work_group_size()]] or + // [intel::reqd_work_group_size()]] attribute can be evenly divided by + // the [[intel::num_simd_work_items()]] attribute. GNU spelling of + // ReqdWorkGroupSizeAttr maps to the OpenCL semantics. First and last + // argument are only swapped for the atributes in SYCL and not the OpenCL ones. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); bool UsesOpenCLArgOrdering = - ((AL.getSyntax() == AttributeCommonInfo::AS_CXX11 || - AL.getSyntax() == AttributeCommonInfo::AS_C2x) && - AL.hasScope() && AL.getScopeName()->isStr("cl")) || AL.getSyntax() == AttributeCommonInfo::AS_GNU; unsigned WorkGroupSize = UsesOpenCLArgOrdering ? XDimVal.getZExtValue() @@ -3299,21 +3295,22 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, } // If the declaration has a [[intel::reqd_work_group_size()]] - // attribute, check to see if the last argument can be evenly - // divided by the num_simd_work_items attribute. + // or [[cl::reqd_work_group_size()]] attribute, check to see + // if the last argument can be evenly divided by the + // [[intel::num_simd_work_items()]] attribute. // If the declaration has a __attribute__((reqd_work_group_size)) - // or [[cl::reqd_work_group_size()]] attribute, check to see if the - // first argument can be evenly divided by the num_simd_work_items - // attribute. GNU and [[cl::reqd_work_group_size()]] spelling of - // ReqdWorkGroupSizeAttr maps to the OpenCL semantics. First and last - // argument are only swapped for the Intel atributes in SYCL and not - // the OpenCL ones. + // attribute, check to see if the first argument can be evenly + // divided by the [[intel::num_simd_work_items()]] attribute. GNU + // spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. + // First and last argument are only swapped for the atributes in SYCL + // and not the OpenCL ones. if (const auto *DeclAttr = D->getAttr()) { - Optional XDimVal = DeclAttr->getXDimVal(Context); - Optional ZDimVal = DeclAttr->getZDimVal(Context); + const auto *DeclXExpr = dyn_cast(DeclAttr->getXDim()); + const auto *DeclZExpr = dyn_cast(DeclAttr->getZDim()); llvm::APSInt WorkGroupSize = - DeclAttr->usesOpenCLArgOrdering() ? *XDimVal : *ZDimVal; + DeclAttr->usesOpenCLArgOrdering() ? DeclXExpr->getResultAsAPSInt() + : DeclZExpr->getResultAsAPSInt(); if (WorkGroupSize % ArgVal != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) diff --git a/clang/test/SemaSYCL/num_simd_work_items_device.cpp b/clang/test/SemaSYCL/num_simd_work_items_device.cpp index 0a4624b8a48ad..09647cf418d31 100644 --- a/clang/test/SemaSYCL/num_simd_work_items_device.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items_device.cpp @@ -43,9 +43,9 @@ struct FuncObj { #ifdef TRIGGER_ERROR // If the declaration has a [[intel::reqd_work_group_size]] -// attribute, tests that check if the work group size attribute -// argument (the last argument) can be evenly divided by the -// num_simd_work_items attribute. +// [[cl::reqd_work_group_size]] attribute, tests that check +// if the work group size attribute argument (the last argument) +// can be evenly divided by the [[intel::num_simd_work_items()]] attribute. struct TRIFuncObjBad1 { [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} [[intel::reqd_work_group_size(3, 6, 5)]] // expected-note{{conflicting attribute is here}} @@ -88,36 +88,41 @@ struct TRIFuncObjBad6 { operator()() const {} }; -[[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} -[[intel::reqd_work_group_size(4, 2, 3)]] void func1(); // expected-note{{conflicting attribute is here}} - -// If the declaration has a [[cl::reqd_work_group_size]] -// or __attribute__((reqd_work_group_size())) attribute, -// tests that check if the work group size attribute argument -// (the first argument) can be evenly divided by the num_simd_work_items -// attribute. GNU and [[cl::reqd_work_group_size]] spelling of -// ReqdWorkGroupSizeAttr maps to the OpenCL semantics. -// First and last argument are only swapped for the Intel atributes in -// SYCL and not the OpenCL ones. struct TRIFuncObjBad7 { - [[cl::reqd_work_group_size(5, 6, 8)]] // expected-note{{conflicting attribute is here}} - [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[cl::reqd_work_group_size(6, 3, 5)]] // expected-note{{conflicting attribute is here}} + [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} void operator()() const {} }; struct TRIFuncObjBad8 { - [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} - [[cl::reqd_work_group_size(5, 6, 8)]] // expected-note{{conflicting attribute is here}} + [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + [[cl::reqd_work_group_size(6, 3, 5)]] // expected-note{{conflicting attribute is here}} void operator()() const {} }; [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} -__attribute__((reqd_work_group_size(3, 2, 4))) void func2(); // expected-note{{conflicting attribute is here}} +[[intel::reqd_work_group_size(4, 2, 3)]] void func1(); // expected-note{{conflicting attribute is here}} + +[[intel::reqd_work_group_size(4, 2, 3)]] // expected-note{{conflicting attribute is here}} +[[intel::num_simd_work_items(2)]] void func2(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +[[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} +[[cl::reqd_work_group_size(4, 2, 3)]] void func3(); // expected-note{{conflicting attribute is here}} + +[[cl::reqd_work_group_size(4, 2, 3)]] // expected-note{{conflicting attribute is here}} +[[intel::num_simd_work_items(2)]] void func4(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +// If the declaration has a __attribute__((reqd_work_group_size())) +// attribute, tests that check if the work group size attribute argument +// (the first argument) can be evenly divided by the [[intel::num_simd_work_items()]] +// attribute. GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. +// First and last argument are only swapped for the Intel atributes in +// SYCL and not the OpenCL ones. [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} -[[cl::reqd_work_group_size(5, 2, 4)]] void func3(); // expected-note{{conflicting attribute is here}} +__attribute__((reqd_work_group_size(3, 2, 4))) void func5(); // expected-note{{conflicting attribute is here}} // Tests for incorrect argument values for Intel FPGA num_simd_work_items and reqd_work_group_size function attributes struct TRIFuncObjBad9 { @@ -182,15 +187,15 @@ struct TRIFuncObjBad18 { #endif // TRIGGER_ERROR // If the declaration has a [[intel::reqd_work_group_size()]] -// attribute, check to see if the last argument can be evenly -// divided by the num_simd_work_items attribute. +// or [[cl::reqd_work_group_size()]] attribute, check to see +// if the last argument can be evenly divided by the +// [[intel::num_simd_work_items()]] attribute. // If the declaration has a __attribute__((reqd_work_group_size)) -// or [[cl::reqd_work_group_size()]] attribute, check to see if the -// first argument can be evenly divided by the num_simd_work_items -// attribute. GNU and [[cl::reqd_work_group_size()]] spelling of -// ReqdWorkGroupSizeAttr maps to the OpenCL semantics. First and last -// argument are only swapped for the Intel atributes in SYCL and not -// the OpenCL ones. +// attribute, check to see if the first argument can be evenly +// divided by the [[intel::num_simd_work_items()]] attribute. +// GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. +// First and last argument are only swapped for the Intel atributes in +// SYCL and not the OpenCL ones. struct TRIFuncObjGood1 { [[intel::num_simd_work_items(4)]] [[intel::reqd_work_group_size(3, 64, 4)]] void @@ -205,18 +210,18 @@ struct TRIFuncObjGood2 { struct TRIFuncObjGood3 { [[intel::num_simd_work_items(4)]] - [[cl::reqd_work_group_size(4, 64, 5)]] void + [[cl::reqd_work_group_size(3, 64, 4)]] void operator()() const {} }; struct TRIFuncObjGood4 { - [[cl::reqd_work_group_size(4, 64, 5)]] + [[cl::reqd_work_group_size(3, 64, 4)]] [[intel::num_simd_work_items(4)]] void operator()() const {} }; [[intel::num_simd_work_items(2)]] -__attribute__((reqd_work_group_size(4,3,3))) void func4(); //OK +__attribute__((reqd_work_group_size(4,3,3))) void func6(); //OK int main() { q.submit([&](handler &h) { @@ -287,27 +292,27 @@ int main() { // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK: ReqdWorkGroupSizeAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 4 - // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + // CHECK-NEXT: value: Int 3 + // CHECK-NEXT: IntegerLiteral{{.*}}3{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 64 // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 5 - // CHECK-NEXT: IntegerLiteral{{.*}}5{{$}} + // CHECK-NEXT: value: Int 4 + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} h.single_task(TRIFuncObjGood4()); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel7 // CHECK: ReqdWorkGroupSizeAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 4 - // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + // CHECK-NEXT: value: Int 3 + // CHECK-NEXT: IntegerLiteral{{.*}}3{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 64 // CHECK-NEXT: IntegerLiteral{{.*}}64{{$}} // CHECK-NEXT: ConstantExpr{{.*}}'int' - // CHECK-NEXT: value: Int 5 - // CHECK-NEXT: IntegerLiteral{{.*}}5{{$}} + // CHECK-NEXT: value: Int 4 + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} // CHECK-NEXT: ConstantExpr{{.*}}'int' // CHECK-NEXT: value: Int 4 From b83b6ad47714668b856588e116df2e1a1855686e Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 19:38:53 -0700 Subject: [PATCH 04/20] Fix clang format issues Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f2d120bd62aea..ccf6a291926fd 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3087,12 +3087,13 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { ZDimExpr = ZDim.get(); // If the declaration has an [[intel::num_simd_work_items()]] attribute, - // check to see if the first argument of __attribute__((reqd_work_group_size)) - // attribute and last argument of [[cl::reqd_work_group_size()]] or - // [intel::reqd_work_group_size()]] attribute can be evenly divided by - // the [[intel::num_simd_work_items()]] attribute. GNU spelling of - // ReqdWorkGroupSizeAttr maps to the OpenCL semantics. First and last - // argument are only swapped for the atributes in SYCL and not the OpenCL ones. + // check to see if the first argument of + // __attribute__((reqd_work_group_size)) attribute and last argument of + // [[cl::reqd_work_group_size()]] or [intel::reqd_work_group_size()]] + // attribute can be evenly divided by the [[intel::num_simd_work_items()]] + // attribute. GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL + // semantics. First and last argument are only swapped for the atributes in + // SYCL and not the OpenCL ones. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); @@ -3308,9 +3309,9 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, const auto *DeclXExpr = dyn_cast(DeclAttr->getXDim()); const auto *DeclZExpr = dyn_cast(DeclAttr->getZDim()); - llvm::APSInt WorkGroupSize = - DeclAttr->usesOpenCLArgOrdering() ? DeclXExpr->getResultAsAPSInt() - : DeclZExpr->getResultAsAPSInt(); + llvm::APSInt WorkGroupSize = DeclAttr->usesOpenCLArgOrdering() + ? DeclXExpr->getResultAsAPSInt() + : DeclZExpr->getResultAsAPSInt(); if (WorkGroupSize % ArgVal != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) From e23fc8b55c631565073de28f2c5bb6424184fec4 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 21:32:38 -0700 Subject: [PATCH 05/20] check null values for reqd_work_group_size attribute Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 40 ++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ccf6a291926fd..502bc95faba3f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3306,18 +3306,38 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, // First and last argument are only swapped for the atributes in SYCL // and not the OpenCL ones. if (const auto *DeclAttr = D->getAttr()) { - const auto *DeclXExpr = dyn_cast(DeclAttr->getXDim()); - const auto *DeclZExpr = dyn_cast(DeclAttr->getZDim()); + Expr *XDimExpr = DeclAttr->getXDim(); + Expr *YDimExpr = DeclAttr->getYDim(); + Expr *ZDimExpr = DeclAttr->getZDim(); + + if (!XDimExpr->isValueDependent() && !YDimExpr->isValueDependent() + && !ZDimExpr->isValueDependent()) { + llvm::APSInt XDimVal, YDimVal, ZDimVal; + ExprResult XDim = VerifyIntegerConstantExpression(XDimExpr, &XDimVal); + ExprResult YDim = VerifyIntegerConstantExpression(YDimExpr, &YDimVal); + ExprResult ZDim = VerifyIntegerConstantExpression(ZDimExpr, &ZDimVal); + + if (XDim.isInvalid()) + return; + XDimExpr = XDim.get(); - llvm::APSInt WorkGroupSize = DeclAttr->usesOpenCLArgOrdering() - ? DeclXExpr->getResultAsAPSInt() - : DeclZExpr->getResultAsAPSInt(); + if (YDim.isInvalid()) + return; + YDimExpr = YDim.get(); - if (WorkGroupSize % ArgVal != 0) { - Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) - << CI << DeclAttr; - Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute); - return; + if (ZDim.isInvalid()) + return; + ZDimExpr = ZDim.get(); + + llvm::APSInt WorkGroupSize = DeclAttr->usesOpenCLArgOrdering() + ? XDimVal : ZDimVal; + + if (WorkGroupSize % ArgVal != 0) { + Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) + << CI << DeclAttr; + Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute); + return; + } } } } From b163449fcadf8b3a7a775cbba7beb0fc90337fc5 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 21:40:02 -0700 Subject: [PATCH 06/20] Fix clang format issues Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 502bc95faba3f..d6c5523c82482 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3310,8 +3310,8 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, Expr *YDimExpr = DeclAttr->getYDim(); Expr *ZDimExpr = DeclAttr->getZDim(); - if (!XDimExpr->isValueDependent() && !YDimExpr->isValueDependent() - && !ZDimExpr->isValueDependent()) { + if (!XDimExpr->isValueDependent() && !YDimExpr->isValueDependent() && + !ZDimExpr->isValueDependent()) { llvm::APSInt XDimVal, YDimVal, ZDimVal; ExprResult XDim = VerifyIntegerConstantExpression(XDimExpr, &XDimVal); ExprResult YDim = VerifyIntegerConstantExpression(YDimExpr, &YDimVal); @@ -3329,15 +3329,15 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, return; ZDimExpr = ZDim.get(); - llvm::APSInt WorkGroupSize = DeclAttr->usesOpenCLArgOrdering() - ? XDimVal : ZDimVal; + llvm::APSInt WorkGroupSize = + DeclAttr->usesOpenCLArgOrdering() ? XDimVal : ZDimVal; if (WorkGroupSize % ArgVal != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) << CI << DeclAttr; Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute); return; - } + } } } } From e9d781243204ad11793fccb8ace74595e272f5f0 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 22:04:13 -0700 Subject: [PATCH 07/20] update patch Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d6c5523c82482..397d8b25168f4 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3095,20 +3095,25 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { // semantics. First and last argument are only swapped for the atributes in // SYCL and not the OpenCL ones. if (const auto *A = D->getAttr()) { - int64_t NumSimdWorkItems = - A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); - - bool UsesOpenCLArgOrdering = + Expr *E = A->getValue(); + if (!E->isValueDependent()) { + llvm::APSInt ArgVal; + ExprResult Res = S.VerifyIntegerConstantExpression(E, &ArgVal); + if (Res.isInvalid()) + return; + E = Res.get(); + bool UsesOpenCLArgOrdering = AL.getSyntax() == AttributeCommonInfo::AS_GNU; - unsigned WorkGroupSize = UsesOpenCLArgOrdering ? XDimVal.getZExtValue() - : ZDimVal.getZExtValue(); + llvm::APSInt WorkGroupSize = UsesOpenCLArgOrdering + ? XDimVal : ZDimVal; - if (WorkGroupSize % NumSimdWorkItems != 0) { - S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) - << A << AL; - S.Diag(AL.getLoc(), diag::note_conflicting_attribute); - return; + if (WorkGroupSize % ArgVal != 0) { + S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) + << A << AL; + S.Diag(AL.getLoc(), diag::note_conflicting_attribute); + return; + } } } From 9c8643c1e77fbc7e70b93e6314679f0196cde43e Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Tue, 11 May 2021 22:09:49 -0700 Subject: [PATCH 08/20] update patch Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 397d8b25168f4..d6c5523c82482 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3095,25 +3095,20 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { // semantics. First and last argument are only swapped for the atributes in // SYCL and not the OpenCL ones. if (const auto *A = D->getAttr()) { - Expr *E = A->getValue(); - if (!E->isValueDependent()) { - llvm::APSInt ArgVal; - ExprResult Res = S.VerifyIntegerConstantExpression(E, &ArgVal); - if (Res.isInvalid()) - return; - E = Res.get(); - bool UsesOpenCLArgOrdering = + int64_t NumSimdWorkItems = + A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); + + bool UsesOpenCLArgOrdering = AL.getSyntax() == AttributeCommonInfo::AS_GNU; - llvm::APSInt WorkGroupSize = UsesOpenCLArgOrdering - ? XDimVal : ZDimVal; + unsigned WorkGroupSize = UsesOpenCLArgOrdering ? XDimVal.getZExtValue() + : ZDimVal.getZExtValue(); - if (WorkGroupSize % ArgVal != 0) { - S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) - << A << AL; - S.Diag(AL.getLoc(), diag::note_conflicting_attribute); - return; - } + if (WorkGroupSize % NumSimdWorkItems != 0) { + S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) + << A << AL; + S.Diag(AL.getLoc(), diag::note_conflicting_attribute); + return; } } From 128a7f96aa883846e8fcb8b73aa2257c75ef1197 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Wed, 12 May 2021 05:44:23 -0700 Subject: [PATCH 09/20] Update patch and add template cases Signed-off-by: Soumi Manna --- clang/include/clang/Basic/AttrDocs.td | 11 +-- ...cl-device-num_simd_work_items-template.cpp | 69 +++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b59872c92d49a..0b72b68d7a2b7 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2623,7 +2623,7 @@ increments the fastest, followed by Y, then Z. If we preserve that definition of X, Y, and Z, then in SYCL the attribute is specified as ``[[intel::reqd_work_group_size(Z, Y, X)]]`` or ``[[cl::reqd_work_group_size(Z, Y, X)]]``. This gets more complicated in the -case where fewer than three arguments are provided since +-case where fewer than three arguments are provided since ``[[intel::reqd_work_group_size(Z, Y, X)]]`` attribute spelling allows the Y and Z arguments to be optional. In such a case it's not the ``X`` argument that is omitted (by the definitions of X, Y, and Z above) it's the ``Z`` @@ -2668,10 +2668,11 @@ Fore more information, see the documentation about required work-group size. If the ``__attribute__((reqd_work_group_size()))`` attribute is specified on a declaration along with a ``intel::num_simd_work_items`` attribute, the required work-group size (``X`` dimention, which is the first -dimension in the reqd_work_group_size) must be evenly divisible by -the argument specified in the ``intel::num_simd_work_items`` attribute. -GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantic. The first and -last dimension are only swapped for the attributes in SYCL and not the OpenCL ones. +dimension in the reqd_work_group_size by the definitions of X, Y, and Z above) +must be evenly divisible by the argument specified in the +``intel::num_simd_work_items`` attribute. GNU spelling of ReqdWorkGroupSizeAttr +maps to the OpenCL semantic. The first and last dimension are only swapped for +the attributes in SYCL and not the OpenCL ones. .. code-block:: c++ diff --git a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp index b9445054752f8..f9e074364efd9 100644 --- a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp @@ -93,3 +93,72 @@ int check() { // CHECK-NEXT: ConstantExpr {{.*}} 'int' // CHECK-NEXT: value: Int 2 // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} + +// Tests for num_simd_work_items and reqd_work_group_size arguments check. +template +__attribute__((reqd_work_group_size(3, 6, 4))) void func6(); // expected-note{{conflicting attribute is here}} +template +[[intel::num_simd_work_items(N)]] void func6(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +template +[[cl::reqd_work_group_size(8, 4, 5)]] void func7(); // expected-note{{conflicting attribute is here}} +template +[[intel::num_simd_work_items(N)]] void func7(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +template +[[intel::reqd_work_group_size(N, N, N)]] void func8(); // expected-note{{conflicting attribute is here}} +template +[[intel::num_simd_work_items(3)]] void func8(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +template +[[intel::reqd_work_group_size(X, Y, Z)]] void func9(); // expected-note{{conflicting attribute is here}} +template +[[intel::num_simd_work_items(N)]] void func9(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +template +[[intel::reqd_work_group_size(X, Y, Z)]] void func10(); // expected-note{{conflicting attribute is here}} +template +[[intel::num_simd_work_items(3)]] void func10(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +template +[[cl::reqd_work_group_size(X, Y, Z)]] void func11(); // expected-note{{conflicting attribute is here}} +template +[[intel::num_simd_work_items(2)]] void func11(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +template +[[cl::reqd_work_group_size(N, N, N)]] void func12(); // expected-note{{conflicting attribute is here}} +template +[[intel::num_simd_work_items(2)]] void func12(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} + +int check1() { + // no error expected + func6<3>(); + //expected-note@+1{{in instantiation of function template specialization 'func6<2>' requested here}} + func6<2>(); + //expected-note@+1{{in instantiation of function template specialization 'func7<4>' requested here}} + func7<4>(); + // no error expected + func7<5>(); + //expected-note@+1{{in instantiation of function template specialization 'func8<5>' requested here}} + func8<5>(); + // no error expected + func8<3>(); + //expected-note@+1{{in instantiation of function template specialization 'func9<6, 3, 5, 3>' requested here}} + func9<6, 3, 5, 3>(); + // no error expected + func9<9, 6, 3, 3>(); + //expected-note@+1{{in instantiation of function template specialization 'func10<6, 3, 5>' requested here}} + func10<6, 3, 5>(); + // no error expected + func10<9, 6, 3>(); + //expected-note@+1{{in instantiation of function template specialization 'func11<6, 4, 5>' requested here}} + func11<6, 4, 5>(); + // no error expected + func11<8, 6, 2>(); + //expected-note@+1{{in instantiation of function template specialization 'func12<3>' requested here}} + func12<3>(); + // no error expected + func12<2>(); + return 0; +} + From e4bc13fe65af7ab0e0320d25f17229296276adbd Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Wed, 12 May 2021 17:23:26 -0700 Subject: [PATCH 10/20] address review comments Signed-off-by: Soumi Manna --- clang/include/clang/Basic/AttrDocs.td | 128 +++++++++++++----- .../SemaSYCL/num_simd_work_items_device.cpp | 26 ++++ ...cl-device-num_simd_work_items-template.cpp | 43 ++---- 3 files changed, 134 insertions(+), 63 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 0b72b68d7a2b7..bff33e0ff7e14 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2503,6 +2503,69 @@ device kernel, the attribute is not ignored and it is propagated to the kernel. [[intel::num_simd_work_items(N)]] void operator()() const {} }; +The arguments to reqd_work_group_size are ordered based on which index +increments the fastest. In OpenCL, the first argument is the index that +increments the fastest, and in SYCL, the last argument is the index that +increments the fastest. + +In OpenCL, all three arguments are required. + +In SYCL, the attribute accepts either one, two, or three arguments; in each +form, the last (or only) argument is the index that increments fastest. +The number of arguments passed to the attribute must match the dimensionality +of the kernel the attribute is applied to. + +If the reqd_work_group_size attribute is specified on a declaration along +with ``intel::num_simd_work_items``, the required work group size specified +by ``intel::num_simd_work_items`` attribute must evenly divide the index that +increments fastest in the reqd_work_group_size attribute. + +.. code-block:: c++ + + struct func { + [[intel::num_simd_work_items(4)]] + [[intel::reqd_work_group_size(3, 4, 64)]] + void operator()() const {} + }; + + struct bar { + [[intel::reqd_work_group_size(3, 4, 64)]] + [[intel::num_simd_work_items(4)]] + void operator()() const {} + }; + + [[intel::reqd_work_group_size(5)]] + // identical to [[intel::reqd_work_group_size(5, 1, 1)]] + [[intel::num_simd_work_items(5)]] void fun() {} + + [[intel::reqd_work_group_size(5, 10)]] + // identical to [[intel::reqd_work_group_size(5, 10, 1)]] + [[intel::num_simd_work_items(5)]] void fun1() {} + + [[cl::reqd_work_group_size(7, 10, 20)]] + [[intel::num_simd_work_items(5)]] void fun2() {} + + [[intel::num_simd_work_items(4)]] + [[cl::reqd_work_group_size(5, 4, 8)]] void fun3() {} + + struct func1 { + [[intel::num_simd_work_items(4)]] + [[cl::reqd_work_group_size(5, 4, 64)]] + void operator()() const {} + }; + + struct bar1 { + [[cl::reqd_work_group_size(3, 4, 64)]] + [[intel::num_simd_work_items(4)]] + void operator()() const {} + }; + + [[intel::num_simd_work_items(2)]] + __attribute__((reqd_work_group_size(4, 2, 3))) void test(); + + __attribute__((reqd_work_group_size(4, 2, 3))) + [[intel::num_simd_work_items(2)]] void test1(); + }]; } @@ -2616,28 +2679,22 @@ In OpenCL C, this attribute is available in GNU spelling __kernel __attribute__((reqd_work_group_size(8, 16, 32))) void test() {} -The order of the arguments to reqd_work_group_size in SYCL and OpenCL are -reversed. In the OpenCL syntax, -(``__attribute__((reqd_work_group_size(X, Y, Z)))``), X is the index that -increments the fastest, followed by Y, then Z. If we preserve that definition -of X, Y, and Z, then in SYCL the attribute is specified as -``[[intel::reqd_work_group_size(Z, Y, X)]]`` or -``[[cl::reqd_work_group_size(Z, Y, X)]]``. This gets more complicated in the --case where fewer than three arguments are provided since -``[[intel::reqd_work_group_size(Z, Y, X)]]`` attribute spelling allows -the Y and Z arguments to be optional. In such a case it's not the ``X`` argument -that is omitted (by the definitions of X, Y, and Z above) it's the ``Z`` -dimension that's omitted. So the two argument version has the syntax -``[[intel::reqd_work_group_size(Y, X)]]``. Similarly, the one argument variant -has syntax ``[[intel::reqd_work_group_size(X)]]``. -In summary, in SYCL if the ``intel::reqd_work_group_size`` or -``cl::reqd_work_group_size`` attribute is specified on a declaration along with -a ``intel::num_simd_work_items`` attribute, the required work-group size -(``X`` dimention, which is the last dimension in the reqd_work_group_size) must -be evenly divisible by the argument specified in the -``intel::num_simd_work_items``. -Fore more information, see the documentation about required work-group size. -..`Specify a Work-Group Size`: https://software.intel.com/content/www/us/en/develop/documentation/oneapi-fpga-optimization-guide/top/optimize-your-design/resource-use/specify-a-work-group-size.html +The arguments to reqd_work_group_size are ordered based on which index +increments the fastest. In OpenCL, the first argument is the index that +increments the fastest, and in SYCL, the last argument is the index that +increments the fastest. + +In OpenCL, all three arguments are required. + +In SYCL, the attribute accepts either one, two, or three arguments; in each +form, the last (or only) argument is the index that increments fastest. The +number of arguments passed to the attribute must match the dimensionality of +the kernel the attribute is applied to. + +If the reqd_work_group_size attribute is specified on a declaration along with +num_simd_work_items, the required work group size specified by num_simd_work_items +must evenly divide the index that increments fastest in the reqd_work_group_size +attribute. .. code-block:: c++ @@ -2653,9 +2710,23 @@ Fore more information, see the documentation about required work-group size. void operator()() const {} }; + [[intel::reqd_work_group_size(5)]] + // identical to [[intel::reqd_work_group_size(5, 1, 1)]] + [[intel::num_simd_work_items(5)]] void fun() {} + + [[intel::reqd_work_group_size(5, 10)]] + // identical to [[intel::reqd_work_group_size(5, 10, 1)]] + [[intel::num_simd_work_items(5)]] void fun1() {} + + [[cl::reqd_work_group_size(7, 10, 20)]] + [[intel::num_simd_work_items(5)]] void fun2() {} + + [[intel::num_simd_work_items(4)]] + [[cl::reqd_work_group_size(5, 4, 8)]] void fun3() {} + struct func1 { [[intel::num_simd_work_items(4)]] - [[cl::reqd_work_group_size(3, 4, 64)]] + [[cl::reqd_work_group_size(5, 4, 64)]] void operator()() const {} }; @@ -2665,17 +2736,6 @@ Fore more information, see the documentation about required work-group size. void operator()() const {} }; -If the ``__attribute__((reqd_work_group_size()))`` attribute is specified on -a declaration along with a ``intel::num_simd_work_items`` -attribute, the required work-group size (``X`` dimention, which is the first -dimension in the reqd_work_group_size by the definitions of X, Y, and Z above) -must be evenly divisible by the argument specified in the -``intel::num_simd_work_items`` attribute. GNU spelling of ReqdWorkGroupSizeAttr -maps to the OpenCL semantic. The first and last dimension are only swapped for -the attributes in SYCL and not the OpenCL ones. - -.. code-block:: c++ - [[intel::num_simd_work_items(2)]] __attribute__((reqd_work_group_size(4, 2, 3))) void test(); diff --git a/clang/test/SemaSYCL/num_simd_work_items_device.cpp b/clang/test/SemaSYCL/num_simd_work_items_device.cpp index 09647cf418d31..9cfc76c90e4fa 100644 --- a/clang/test/SemaSYCL/num_simd_work_items_device.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items_device.cpp @@ -60,6 +60,14 @@ struct TRIFuncObjBad2 { operator()() const {} }; +// Tests for the default values of [[intel::reqd_work_group_size()]]. + +// FIXME: This should be accepted instaed of error which turns out to be +// an implementation bug that shouldn't be visible to the user as there +// aren't really any default values. The dimensionality of the attribute +// must match the kernel, so three different forms of the attribute +// (one, two, and three argument) can be used instead of assuming default +// values. This will prevent to redeclare the function with a different dimensionality. struct TRIFuncObjBad3 { [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} [[intel::reqd_work_group_size(3)]] //expected-note{{conflicting attribute is here}} @@ -67,6 +75,12 @@ struct TRIFuncObjBad3 { operator()() const {} }; +// FIXME: This should be accepted instaed of error which turns out to be +// an implementation bug that shouldn't be visible to the user as there +// aren't really any default values. The dimensionality of the attribute +// must match the kernel, so three different forms of the attribute +// (one, two, and three argument) can be used instead of assuming default +// values. This will prevent to redeclare the function with a different dimensionality. struct TRIFuncObjBad4 { [[intel::reqd_work_group_size(3)]] // expected-note{{conflicting attribute is here}} [[intel::num_simd_work_items(3)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} @@ -74,6 +88,12 @@ struct TRIFuncObjBad4 { operator()() const {} }; +// FIXME: This should be accepted instaed of error which turns out to be +// an implementation bug that shouldn't be visible to the user as there +// aren't really any default values. The dimensionality of the attribute +// must match the kernel, so three different forms of the attribute +// (one, two, and three argument) can be used instead of assuming default +// values. This will prevent to redeclare the function with a different dimensionality. struct TRIFuncObjBad5 { [[intel::num_simd_work_items(4)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} [[intel::reqd_work_group_size(4, 64)]] // expected-note{{conflicting attribute is here}} @@ -81,6 +101,12 @@ struct TRIFuncObjBad5 { operator()() const {} }; +// FIXME: This should be accepted instaed of error which turns out to be +// an implementation bug that shouldn't be visible to the user as there +// aren't really any default values. The dimensionality of the attribute +// must match the kernel, so three different forms of the attribute +// (one, two, and three argument) can be used instead of assuming default +// values. This will prevent to redeclare the function with a different dimensionality. struct TRIFuncObjBad6 { [[intel::reqd_work_group_size(4, 64)]] // expected-note{{conflicting attribute is here}} [[intel::num_simd_work_items(4)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} diff --git a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp index f9e074364efd9..ce4dcce524a63 100644 --- a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp @@ -131,34 +131,19 @@ template [[intel::num_simd_work_items(2)]] void func12(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} int check1() { - // no error expected - func6<3>(); - //expected-note@+1{{in instantiation of function template specialization 'func6<2>' requested here}} - func6<2>(); - //expected-note@+1{{in instantiation of function template specialization 'func7<4>' requested here}} - func7<4>(); - // no error expected - func7<5>(); - //expected-note@+1{{in instantiation of function template specialization 'func8<5>' requested here}} - func8<5>(); - // no error expected - func8<3>(); - //expected-note@+1{{in instantiation of function template specialization 'func9<6, 3, 5, 3>' requested here}} - func9<6, 3, 5, 3>(); - // no error expected - func9<9, 6, 3, 3>(); - //expected-note@+1{{in instantiation of function template specialization 'func10<6, 3, 5>' requested here}} - func10<6, 3, 5>(); - // no error expected - func10<9, 6, 3>(); - //expected-note@+1{{in instantiation of function template specialization 'func11<6, 4, 5>' requested here}} - func11<6, 4, 5>(); - // no error expected - func11<8, 6, 2>(); - //expected-note@+1{{in instantiation of function template specialization 'func12<3>' requested here}} - func12<3>(); - // no error expected - func12<2>(); + func6<3>(); // OK + func6<2>(); // expected-note {{in instantiation of function template specialization 'func6<2>' requested here}} + func7<4>(); // expected-note {{in instantiation of function template specialization 'func7<4>' requested here}} + func7<5>(); // OK + func8<5>(); // expected-note {{in instantiation of function template specialization 'func8<5>' requested here}} + func8<3>(); // OK + func9<6, 3, 5, 3>(); // expected-note {{in instantiation of function template specialization 'func9<6, 3, 5, 3>' requested here}} + func9<9, 6, 3, 3>(); // OK + func10<6, 3, 5>(); // expected-note {{in instantiation of function template specialization 'func10<6, 3, 5>' requested here}} + func10<9, 6, 3>(); // OK + func11<6, 4, 5>(); // expected-note {{in instantiation of function template specialization 'func11<6, 4, 5>' requested here}} + func11<8, 6, 2>(); // OK + func12<3>(); // expected-note {{in instantiation of function template specialization 'func12<3>' requested here}} + func12<2>(); // OK return 0; } - From 4d5363cfa019f0763f6f7f0879aa027ea7075af3 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Wed, 12 May 2021 17:38:33 -0700 Subject: [PATCH 11/20] update doc Signed-off-by: Soumi Manna --- clang/include/clang/Basic/AttrDocs.td | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index bff33e0ff7e14..a539a0e87ef5d 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2534,14 +2534,6 @@ increments fastest in the reqd_work_group_size attribute. void operator()() const {} }; - [[intel::reqd_work_group_size(5)]] - // identical to [[intel::reqd_work_group_size(5, 1, 1)]] - [[intel::num_simd_work_items(5)]] void fun() {} - - [[intel::reqd_work_group_size(5, 10)]] - // identical to [[intel::reqd_work_group_size(5, 10, 1)]] - [[intel::num_simd_work_items(5)]] void fun1() {} - [[cl::reqd_work_group_size(7, 10, 20)]] [[intel::num_simd_work_items(5)]] void fun2() {} @@ -2710,14 +2702,6 @@ attribute. void operator()() const {} }; - [[intel::reqd_work_group_size(5)]] - // identical to [[intel::reqd_work_group_size(5, 1, 1)]] - [[intel::num_simd_work_items(5)]] void fun() {} - - [[intel::reqd_work_group_size(5, 10)]] - // identical to [[intel::reqd_work_group_size(5, 10, 1)]] - [[intel::num_simd_work_items(5)]] void fun1() {} - [[cl::reqd_work_group_size(7, 10, 20)]] [[intel::num_simd_work_items(5)]] void fun2() {} From 8dbf4e27c69445ee4e2ccd2afa6595d88bd6ef4b Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Wed, 12 May 2021 17:43:13 -0700 Subject: [PATCH 12/20] fix typos Signed-off-by: Soumi Manna --- clang/test/SemaSYCL/num_simd_work_items_device.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/test/SemaSYCL/num_simd_work_items_device.cpp b/clang/test/SemaSYCL/num_simd_work_items_device.cpp index 9cfc76c90e4fa..d68b42d6a29cf 100644 --- a/clang/test/SemaSYCL/num_simd_work_items_device.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items_device.cpp @@ -62,7 +62,7 @@ struct TRIFuncObjBad2 { // Tests for the default values of [[intel::reqd_work_group_size()]]. -// FIXME: This should be accepted instaed of error which turns out to be +// FIXME: This should be accepted instead of error which turns out to be // an implementation bug that shouldn't be visible to the user as there // aren't really any default values. The dimensionality of the attribute // must match the kernel, so three different forms of the attribute @@ -75,7 +75,7 @@ struct TRIFuncObjBad3 { operator()() const {} }; -// FIXME: This should be accepted instaed of error which turns out to be +// FIXME: This should be accepted instead of error which turns out to be // an implementation bug that shouldn't be visible to the user as there // aren't really any default values. The dimensionality of the attribute // must match the kernel, so three different forms of the attribute @@ -88,7 +88,7 @@ struct TRIFuncObjBad4 { operator()() const {} }; -// FIXME: This should be accepted instaed of error which turns out to be +// FIXME: This should be accepted instead of error which turns out to be // an implementation bug that shouldn't be visible to the user as there // aren't really any default values. The dimensionality of the attribute // must match the kernel, so three different forms of the attribute @@ -101,7 +101,7 @@ struct TRIFuncObjBad5 { operator()() const {} }; -// FIXME: This should be accepted instaed of error which turns out to be +// FIXME: This should be accepted instead of error which turns out to be // an implementation bug that shouldn't be visible to the user as there // aren't really any default values. The dimensionality of the attribute // must match the kernel, so three different forms of the attribute From ddd73e99792e87739f76843e44a75591f160e599 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Thu, 13 May 2021 10:36:26 -0700 Subject: [PATCH 13/20] address review comments Signed-off-by: Soumi Manna --- clang/include/clang/Basic/Attr.td | 2 +- clang/include/clang/Basic/AttrDocs.td | 90 +++++++++++++------ clang/lib/Sema/SemaDeclAttr.cpp | 14 ++- .../SemaSYCL/num_simd_work_items_device.cpp | 6 -- 4 files changed, 67 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 93988b0ec3a8e..9171144b4bd73 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2944,7 +2944,7 @@ def ReqdWorkGroupSize : InheritableAttr { ExprArgument<"YDim", /*optional*/1>, ExprArgument<"ZDim", /*optional*/1>]; let Subjects = SubjectList<[Function], ErrorDiag>; - let Accessors = [Accessor<"usesOpenCLArgOrdering", + let Accessors = [Accessor<"usesOpenCLSemantics", [GNU<"reqd_work_group_size">]>]; let AdditionalMembers = [{ ArrayRef dimensions() const { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index a539a0e87ef5d..670d71877b567 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2503,7 +2503,7 @@ device kernel, the attribute is not ignored and it is propagated to the kernel. [[intel::num_simd_work_items(N)]] void operator()() const {} }; -The arguments to reqd_work_group_size are ordered based on which index +The arguments to ``reqd_work_group_size`` are ordered based on which index increments the fastest. In OpenCL, the first argument is the index that increments the fastest, and in SYCL, the last argument is the index that increments the fastest. @@ -2515,48 +2515,64 @@ form, the last (or only) argument is the index that increments fastest. The number of arguments passed to the attribute must match the dimensionality of the kernel the attribute is applied to. -If the reqd_work_group_size attribute is specified on a declaration along -with ``intel::num_simd_work_items``, the required work group size specified -by ``intel::num_simd_work_items`` attribute must evenly divide the index that -increments fastest in the reqd_work_group_size attribute. +If the ``reqd_work_group_size`` attribute is specified on a declaration along +with ``num_simd_work_items``, the required work group size specified +by ``num_simd_work_items`` attribute must evenly divide the index that +increments fastest in the ``reqd_work_group_size`` attribute. .. code-block:: c++ + // Note, '64' is evenly divisible by '4'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct func { [[intel::num_simd_work_items(4)]] - [[intel::reqd_work_group_size(3, 4, 64)]] + [[intel::reqd_work_group_size(7, 4, 64)]] void operator()() const {} }; + // Note, '8' is evenly divisible by '8'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct bar { - [[intel::reqd_work_group_size(3, 4, 64)]] - [[intel::num_simd_work_items(4)]] + [[intel::reqd_work_group_size(1, 1, 8)]] + [[intel::num_simd_work_items(8)]] void operator()() const {} }; - [[cl::reqd_work_group_size(7, 10, 20)]] + // Note, '10' is evenly divisible by '5'; in SYCL, the last + // argument to the attribute is the one which increments fastest. + [[cl::reqd_work_group_size(7, 5, 10)]] [[intel::num_simd_work_items(5)]] void fun2() {} + // Note, '8' is evenly divisible by '4'; in SYCL, the last + // argument to the attribute is the one which increments fastest. [[intel::num_simd_work_items(4)]] [[cl::reqd_work_group_size(5, 4, 8)]] void fun3() {} + // Note, '8' is evenly divisible by '8'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct func1 { - [[intel::num_simd_work_items(4)]] - [[cl::reqd_work_group_size(5, 4, 64)]] + [[intel::num_simd_work_items(8)]] + [[cl::reqd_work_group_size(1, 1, 8)]] void operator()() const {} }; + // Note, '8' is evenly divisible by '4'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct bar1 { - [[cl::reqd_work_group_size(3, 4, 64)]] + [[cl::reqd_work_group_size(7, 4, 8)]] [[intel::num_simd_work_items(4)]] void operator()() const {} }; + // Note, '4' is evenly divisible by '2'; in OpenCL, the first + // argument to the attribute is the one which increments fastest. [[intel::num_simd_work_items(2)]] __attribute__((reqd_work_group_size(4, 2, 3))) void test(); - __attribute__((reqd_work_group_size(4, 2, 3))) - [[intel::num_simd_work_items(2)]] void test1(); + // Note, '8' is evenly divisible by '2'; in OpenCL, the first + // argument to the attribute is the one which increments fastest. + __attribute__((reqd_work_group_size(8, 2, 3))) + [intel::num_simd_work_items(2)]] void test(); }]; } @@ -2671,7 +2687,7 @@ In OpenCL C, this attribute is available in GNU spelling __kernel __attribute__((reqd_work_group_size(8, 16, 32))) void test() {} -The arguments to reqd_work_group_size are ordered based on which index +The arguments to ``reqd_work_group_size`` are ordered based on which index increments the fastest. In OpenCL, the first argument is the index that increments the fastest, and in SYCL, the last argument is the index that increments the fastest. @@ -2683,49 +2699,65 @@ form, the last (or only) argument is the index that increments fastest. The number of arguments passed to the attribute must match the dimensionality of the kernel the attribute is applied to. -If the reqd_work_group_size attribute is specified on a declaration along with -num_simd_work_items, the required work group size specified by num_simd_work_items -must evenly divide the index that increments fastest in the reqd_work_group_size -attribute. +If the ``reqd_work_group_size attribute`` is specified on a declaration along +with ``num_simd_work_items``, the required work group size specified by +``num_simd_work_items`` must evenly divide the index that increments fastest +in the ``reqd_work_group_size`` attribute. .. code-block:: c++ + // Note, '64' is evenly divisible by '4'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct func { [[intel::num_simd_work_items(4)]] - [[intel::reqd_work_group_size(3, 4, 64)]] + [[intel::reqd_work_group_size(7, 4, 64)]] void operator()() const {} }; + // Note, '8' is evenly divisible by '8'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct bar { - [[intel::reqd_work_group_size(3, 4, 64)]] - [[intel::num_simd_work_items(4)]] + [[intel::reqd_work_group_size(1, 1, 8)]] + [[intel::num_simd_work_items(8)]] void operator()() const {} }; - [[cl::reqd_work_group_size(7, 10, 20)]] + // Note, '10' is evenly divisible by '5'; in SYCL, the last + // argument to the attribute is the one which increments fastest. + [[cl::reqd_work_group_size(7, 5, 10)]] [[intel::num_simd_work_items(5)]] void fun2() {} + // Note, '8' is evenly divisible by '4'; in SYCL, the last + // argument to the attribute is the one which increments fastest. [[intel::num_simd_work_items(4)]] [[cl::reqd_work_group_size(5, 4, 8)]] void fun3() {} + // Note, '8' is evenly divisible by '8'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct func1 { - [[intel::num_simd_work_items(4)]] - [[cl::reqd_work_group_size(5, 4, 64)]] + [[intel::num_simd_work_items(8)]] + [[cl::reqd_work_group_size(1, 1, 8)]] void operator()() const {} }; + // Note, '8' is evenly divisible by '4'; in SYCL, the last + // argument to the attribute is the one which increments fastest. struct bar1 { - [[cl::reqd_work_group_size(3, 4, 64)]] + [[cl::reqd_work_group_size(7, 4, 8)]] [[intel::num_simd_work_items(4)]] void operator()() const {} }; + // Note, '4' is evenly divisible by '2'; in OpenCL, the first + // argument to the attribute is the one which increments fastest. [[intel::num_simd_work_items(2)]] __attribute__((reqd_work_group_size(4, 2, 3))) void test(); - - __attribute__((reqd_work_group_size(4, 2, 3))) - [[intel::num_simd_work_items(2)]] void test1(); + // Note, '8' is evenly divisible by '2'; in OpenCL, the first + // argument to the attribute is the one which increments fastest. + __attribute__((reqd_work_group_size(8, 2, 3))) + [intel::num_simd_work_items(2)]] void test(); + }]; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d6c5523c82482..1230cb6656c86 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3091,18 +3091,16 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { // __attribute__((reqd_work_group_size)) attribute and last argument of // [[cl::reqd_work_group_size()]] or [intel::reqd_work_group_size()]] // attribute can be evenly divided by the [[intel::num_simd_work_items()]] - // attribute. GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL - // semantics. First and last argument are only swapped for the atributes in - // SYCL and not the OpenCL ones. + // attribute. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); - bool UsesOpenCLArgOrdering = + bool UsesOpenCLSemantics = AL.getSyntax() == AttributeCommonInfo::AS_GNU; - unsigned WorkGroupSize = UsesOpenCLArgOrdering ? XDimVal.getZExtValue() - : ZDimVal.getZExtValue(); + unsigned WorkGroupSize = UsesOpenCLSemantics ? XDimVal.getZExtValue() + : ZDimVal.getZExtValue(); if (WorkGroupSize % NumSimdWorkItems != 0) { S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) @@ -3303,8 +3301,6 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, // attribute, check to see if the first argument can be evenly // divided by the [[intel::num_simd_work_items()]] attribute. GNU // spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. - // First and last argument are only swapped for the atributes in SYCL - // and not the OpenCL ones. if (const auto *DeclAttr = D->getAttr()) { Expr *XDimExpr = DeclAttr->getXDim(); Expr *YDimExpr = DeclAttr->getYDim(); @@ -3330,7 +3326,7 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, ZDimExpr = ZDim.get(); llvm::APSInt WorkGroupSize = - DeclAttr->usesOpenCLArgOrdering() ? XDimVal : ZDimVal; + DeclAttr->usesOpenCLSemantics() ? XDimVal : ZDimVal; if (WorkGroupSize % ArgVal != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) diff --git a/clang/test/SemaSYCL/num_simd_work_items_device.cpp b/clang/test/SemaSYCL/num_simd_work_items_device.cpp index d68b42d6a29cf..437f85d7ee6e3 100644 --- a/clang/test/SemaSYCL/num_simd_work_items_device.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items_device.cpp @@ -144,9 +144,6 @@ struct TRIFuncObjBad8 { // attribute, tests that check if the work group size attribute argument // (the first argument) can be evenly divided by the [[intel::num_simd_work_items()]] // attribute. GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. -// First and last argument are only swapped for the Intel atributes in -// SYCL and not the OpenCL ones. - [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} __attribute__((reqd_work_group_size(3, 2, 4))) void func5(); // expected-note{{conflicting attribute is here}} @@ -219,9 +216,6 @@ struct TRIFuncObjBad18 { // If the declaration has a __attribute__((reqd_work_group_size)) // attribute, check to see if the first argument can be evenly // divided by the [[intel::num_simd_work_items()]] attribute. -// GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. -// First and last argument are only swapped for the Intel atributes in -// SYCL and not the OpenCL ones. struct TRIFuncObjGood1 { [[intel::num_simd_work_items(4)]] [[intel::reqd_work_group_size(3, 64, 4)]] void From 95579a5aff79d8050291c53f86deb5e32f54119b Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Thu, 13 May 2021 10:47:51 -0700 Subject: [PATCH 14/20] fix format issues Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1230cb6656c86..6d63dbed5bd7f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3086,7 +3086,7 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { return; ZDimExpr = ZDim.get(); - // If the declaration has an [[intel::num_simd_work_items()]] attribute, + // If the declaration has a [[intel::num_simd_work_items()]] attribute, // check to see if the first argument of // __attribute__((reqd_work_group_size)) attribute and last argument of // [[cl::reqd_work_group_size()]] or [intel::reqd_work_group_size()]] @@ -3096,11 +3096,10 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); - bool UsesOpenCLSemantics = - AL.getSyntax() == AttributeCommonInfo::AS_GNU; + bool UsesOpenCLSemantics = AL.getSyntax() == AttributeCommonInfo::AS_GNU; - unsigned WorkGroupSize = UsesOpenCLSemantics ? XDimVal.getZExtValue() - : ZDimVal.getZExtValue(); + unsigned WorkGroupSize = + UsesOpenCLSemantics ? XDimVal.getZExtValue() : ZDimVal.getZExtValue(); if (WorkGroupSize % NumSimdWorkItems != 0) { S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) From fa4e4d750295fddc64eb990db2e0aaeb735100d6 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Fri, 14 May 2021 10:26:52 -0700 Subject: [PATCH 15/20] GNU attribute uses SYCL arguments ordering in SYCL mode and OpenCL ordering in OPenCL mode Signed-off-by: Soumi Manna --- clang/include/clang/Basic/Attr.td | 2 -- clang/include/clang/Basic/AttrDocs.td | 16 +++++----- clang/lib/Sema/SemaDeclAttr.cpp | 32 +++++++++---------- .../SemaSYCL/num_simd_work_items_device.cpp | 14 ++++---- ...cl-device-num_simd_work_items-template.cpp | 2 +- 5 files changed, 30 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 9171144b4bd73..a05fe355d314d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2944,8 +2944,6 @@ def ReqdWorkGroupSize : InheritableAttr { ExprArgument<"YDim", /*optional*/1>, ExprArgument<"ZDim", /*optional*/1>]; let Subjects = SubjectList<[Function], ErrorDiag>; - let Accessors = [Accessor<"usesOpenCLSemantics", - [GNU<"reqd_work_group_size">]>]; let AdditionalMembers = [{ ArrayRef dimensions() const { return {getXDim(), getYDim(), getZDim()}; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 670d71877b567..f9a8bc5ce85c2 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2564,14 +2564,14 @@ increments fastest in the ``reqd_work_group_size`` attribute. void operator()() const {} }; - // Note, '4' is evenly divisible by '2'; in OpenCL, the first + // Note, '4' is evenly divisible by '2'; in SYCL, the last // argument to the attribute is the one which increments fastest. [[intel::num_simd_work_items(2)]] - __attribute__((reqd_work_group_size(4, 2, 3))) void test(); + __attribute__((reqd_work_group_size(3, 2, 4))) void test(); - // Note, '8' is evenly divisible by '2'; in OpenCL, the first + // Note, '8' is evenly divisible by '2'; in OpenCL, the last // argument to the attribute is the one which increments fastest. - __attribute__((reqd_work_group_size(8, 2, 3))) + __attribute__((reqd_work_group_size(3, 2, 8))) [intel::num_simd_work_items(2)]] void test(); }]; @@ -2748,14 +2748,14 @@ in the ``reqd_work_group_size`` attribute. void operator()() const {} }; - // Note, '4' is evenly divisible by '2'; in OpenCL, the first + // Note, '4' is evenly divisible by '2'; in SYCL, the last // argument to the attribute is the one which increments fastest. [[intel::num_simd_work_items(2)]] - __attribute__((reqd_work_group_size(4, 2, 3))) void test(); + __attribute__((reqd_work_group_size(3, 2, 4))) void test(); - // Note, '8' is evenly divisible by '2'; in OpenCL, the first + // Note, '8' is evenly divisible by '2'; in SYCL, the last // argument to the attribute is the one which increments fastest. - __attribute__((reqd_work_group_size(8, 2, 3))) + __attribute__((reqd_work_group_size(3, 2, 8))) [intel::num_simd_work_items(2)]] void test(); }]; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 6d63dbed5bd7f..c1885bd8f5fad 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3088,18 +3088,18 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { // If the declaration has a [[intel::num_simd_work_items()]] attribute, // check to see if the first argument of - // __attribute__((reqd_work_group_size)) attribute and last argument of - // [[cl::reqd_work_group_size()]] or [intel::reqd_work_group_size()]] - // attribute can be evenly divided by the [[intel::num_simd_work_items()]] - // attribute. + // __attribute__((reqd_work_group_size)) attribute on OpenCL mode and + // last argument of [[cl::reqd_work_group_size()]] or + // [intel::reqd_work_group_size()]] attribute or + // __attribute__((reqd_work_group_size)) attribute on SYCL mode can be + // evenly divided by the [[intel::num_simd_work_items()]] attribute. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); - bool UsesOpenCLSemantics = AL.getSyntax() == AttributeCommonInfo::AS_GNU; - - unsigned WorkGroupSize = - UsesOpenCLSemantics ? XDimVal.getZExtValue() : ZDimVal.getZExtValue(); + unsigned WorkGroupSize = S.getLangOpts().OpenCL + ? XDimVal.getZExtValue() + : ZDimVal.getZExtValue(); if (WorkGroupSize % NumSimdWorkItems != 0) { S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) @@ -3297,9 +3297,9 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, // if the last argument can be evenly divided by the // [[intel::num_simd_work_items()]] attribute. // If the declaration has a __attribute__((reqd_work_group_size)) - // attribute, check to see if the first argument can be evenly - // divided by the [[intel::num_simd_work_items()]] attribute. GNU - // spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. + // attribute, check to see if the first argument on OpenCL mode and + // last argument on SYCL mode can be evenly divided by the + // [[intel::num_simd_work_items()]] attribute. if (const auto *DeclAttr = D->getAttr()) { Expr *XDimExpr = DeclAttr->getXDim(); Expr *YDimExpr = DeclAttr->getYDim(); @@ -3314,20 +3314,18 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, if (XDim.isInvalid()) return; - XDimExpr = XDim.get(); if (YDim.isInvalid()) return; - YDimExpr = YDim.get(); if (ZDim.isInvalid()) return; - ZDimExpr = ZDim.get(); - llvm::APSInt WorkGroupSize = - DeclAttr->usesOpenCLSemantics() ? XDimVal : ZDimVal; + unsigned WorkGroupSize = getLangOpts().OpenCL + ? XDimVal.getZExtValue() + : ZDimVal.getZExtValue(); - if (WorkGroupSize % ArgVal != 0) { + if (WorkGroupSize % ArgVal.getSExtValue() != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) << CI << DeclAttr; Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute); diff --git a/clang/test/SemaSYCL/num_simd_work_items_device.cpp b/clang/test/SemaSYCL/num_simd_work_items_device.cpp index 437f85d7ee6e3..6e573353894a7 100644 --- a/clang/test/SemaSYCL/num_simd_work_items_device.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items_device.cpp @@ -142,10 +142,10 @@ struct TRIFuncObjBad8 { // If the declaration has a __attribute__((reqd_work_group_size())) // attribute, tests that check if the work group size attribute argument -// (the first argument) can be evenly divided by the [[intel::num_simd_work_items()]] -// attribute. GNU spelling of ReqdWorkGroupSizeAttr maps to the OpenCL semantics. +// (the last argument) can be evenly divided by the [[intel::num_simd_work_items()]] +// attribute. [[intel::num_simd_work_items(2)]] // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} -__attribute__((reqd_work_group_size(3, 2, 4))) void func5(); // expected-note{{conflicting attribute is here}} +__attribute__((reqd_work_group_size(4, 2, 5))) void func5(); // expected-note{{conflicting attribute is here}} // Tests for incorrect argument values for Intel FPGA num_simd_work_items and reqd_work_group_size function attributes struct TRIFuncObjBad9 { @@ -210,12 +210,10 @@ struct TRIFuncObjBad18 { #endif // TRIGGER_ERROR // If the declaration has a [[intel::reqd_work_group_size()]] -// or [[cl::reqd_work_group_size()]] attribute, check to see +// or [[cl::reqd_work_group_size()]] or +// __attribute__((reqd_work_group_size)) attribute, check to see // if the last argument can be evenly divided by the // [[intel::num_simd_work_items()]] attribute. -// If the declaration has a __attribute__((reqd_work_group_size)) -// attribute, check to see if the first argument can be evenly -// divided by the [[intel::num_simd_work_items()]] attribute. struct TRIFuncObjGood1 { [[intel::num_simd_work_items(4)]] [[intel::reqd_work_group_size(3, 64, 4)]] void @@ -241,7 +239,7 @@ struct TRIFuncObjGood4 { }; [[intel::num_simd_work_items(2)]] -__attribute__((reqd_work_group_size(4,3,3))) void func6(); //OK +__attribute__((reqd_work_group_size(3, 2, 6))) void func6(); //OK int main() { q.submit([&](handler &h) { diff --git a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp index ce4dcce524a63..ea43ce8631d13 100644 --- a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp @@ -96,7 +96,7 @@ int check() { // Tests for num_simd_work_items and reqd_work_group_size arguments check. template -__attribute__((reqd_work_group_size(3, 6, 4))) void func6(); // expected-note{{conflicting attribute is here}} +__attribute__((reqd_work_group_size(8, 6, 3))) void func6(); // expected-note{{conflicting attribute is here}} template [[intel::num_simd_work_items(N)]] void func6(); // expected-error{{'num_simd_work_items' attribute must evenly divide the work-group size for the 'reqd_work_group_size' attribute}} From 0057e9a74a5786af2bcc183121def45256d20adb Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Fri, 14 May 2021 10:30:53 -0700 Subject: [PATCH 16/20] fix calng formt issues Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c1885bd8f5fad..983a7873cb965 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3097,9 +3097,8 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); - unsigned WorkGroupSize = S.getLangOpts().OpenCL - ? XDimVal.getZExtValue() - : ZDimVal.getZExtValue(); + unsigned WorkGroupSize = S.getLangOpts().OpenCL ? XDimVal.getZExtValue() + : ZDimVal.getZExtValue(); if (WorkGroupSize % NumSimdWorkItems != 0) { S.Diag(A->getLocation(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) @@ -3321,9 +3320,8 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, if (ZDim.isInvalid()) return; - unsigned WorkGroupSize = getLangOpts().OpenCL - ? XDimVal.getZExtValue() - : ZDimVal.getZExtValue(); + unsigned WorkGroupSize = getLangOpts().OpenCL ? XDimVal.getZExtValue() + : ZDimVal.getZExtValue(); if (WorkGroupSize % ArgVal.getSExtValue() != 0) { Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) From c4e8cc1c0db844d267133d7a52d64c3b797c9b7f Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Fri, 14 May 2021 10:32:52 -0700 Subject: [PATCH 17/20] update doc Signed-off-by: Soumi Manna --- clang/include/clang/Basic/AttrDocs.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index f9a8bc5ce85c2..46a4915511304 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2569,7 +2569,7 @@ increments fastest in the ``reqd_work_group_size`` attribute. [[intel::num_simd_work_items(2)]] __attribute__((reqd_work_group_size(3, 2, 4))) void test(); - // Note, '8' is evenly divisible by '2'; in OpenCL, the last + // Note, '8' is evenly divisible by '2'; in SYCL, the last // argument to the attribute is the one which increments fastest. __attribute__((reqd_work_group_size(3, 2, 8))) [intel::num_simd_work_items(2)]] void test(); From bcd55f2341fcfe52afef7676da5d6935a631913a Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Fri, 14 May 2021 11:55:13 -0700 Subject: [PATCH 18/20] address review comments Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 44 +++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 983a7873cb965..1ada0041e1ae8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3086,13 +3086,20 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { return; ZDimExpr = ZDim.get(); - // If the declaration has a [[intel::num_simd_work_items()]] attribute, - // check to see if the first argument of - // __attribute__((reqd_work_group_size)) attribute on OpenCL mode and - // last argument of [[cl::reqd_work_group_size()]] or - // [intel::reqd_work_group_size()]] attribute or - // __attribute__((reqd_work_group_size)) attribute on SYCL mode can be - // evenly divided by the [[intel::num_simd_work_items()]] attribute. + // If the declaration has a [[intel::reqd_work_group_size()]] + // or [[cl::reqd_work_group_size()]] attribute, check to see + // if the last argument can be evenly divided by the + // [[intel::num_simd_work_items()]] attribute. + // + // __attribute__((reqd_work_group_size)) attribute behaves the + // OpenCL way in OpenCL mode (using the OpenCL semantics) and + // the SYCL way in SYCL mode (using the SYCL semantics). + // If the declaration has a __attribute__((reqd_work_group_size)) + // attribute, check to see if the first argument can be evenly divided + // by the [[intel::num_simd_work_items()]] attribute in OpenCL mode. + // If the declaration has a __attribute__((reqd_work_group_size)) + // attribute, check to see if the last argument can be evenly divided + // by the [[intel::num_simd_work_items()]] attribute in SYCL mode. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); @@ -3295,10 +3302,16 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, // or [[cl::reqd_work_group_size()]] attribute, check to see // if the last argument can be evenly divided by the // [[intel::num_simd_work_items()]] attribute. + // + // __attribute__((reqd_work_group_size)) attribute behaves the + // OpenCL way in OpenCL mode (using the OpenCL semantics) and + // the SYCL way in SYCL mode (using the SYCL semantics). // If the declaration has a __attribute__((reqd_work_group_size)) - // attribute, check to see if the first argument on OpenCL mode and - // last argument on SYCL mode can be evenly divided by the - // [[intel::num_simd_work_items()]] attribute. + // attribute, check to see if the first argument can be evenly divided + // by the [[intel::num_simd_work_items()]] attribute in OpenCL mode. + // If the declaration has a __attribute__((reqd_work_group_size)) + // attribute, check to see if the last argument can be evenly divided + // by the [[intel::num_simd_work_items()]] attribute in SYCL mode. if (const auto *DeclAttr = D->getAttr()) { Expr *XDimExpr = DeclAttr->getXDim(); Expr *YDimExpr = DeclAttr->getYDim(); @@ -3306,18 +3319,11 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, if (!XDimExpr->isValueDependent() && !YDimExpr->isValueDependent() && !ZDimExpr->isValueDependent()) { - llvm::APSInt XDimVal, YDimVal, ZDimVal; + llvm::APSInt XDimVal, ZDimVal; ExprResult XDim = VerifyIntegerConstantExpression(XDimExpr, &XDimVal); - ExprResult YDim = VerifyIntegerConstantExpression(YDimExpr, &YDimVal); ExprResult ZDim = VerifyIntegerConstantExpression(ZDimExpr, &ZDimVal); - if (XDim.isInvalid()) - return; - - if (YDim.isInvalid()) - return; - - if (ZDim.isInvalid()) + if (XDim.isInvalid() || ZDim.isInvalid()) return; unsigned WorkGroupSize = getLangOpts().OpenCL ? XDimVal.getZExtValue() From 1464c3028b8b1aaddc0aa22a70883a5665a5445c Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Fri, 14 May 2021 11:59:08 -0700 Subject: [PATCH 19/20] update comments Signed-off-by: Soumi Manna --- clang/lib/Sema/SemaDeclAttr.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1ada0041e1ae8..e48794168ae0a 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3094,12 +3094,6 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { // __attribute__((reqd_work_group_size)) attribute behaves the // OpenCL way in OpenCL mode (using the OpenCL semantics) and // the SYCL way in SYCL mode (using the SYCL semantics). - // If the declaration has a __attribute__((reqd_work_group_size)) - // attribute, check to see if the first argument can be evenly divided - // by the [[intel::num_simd_work_items()]] attribute in OpenCL mode. - // If the declaration has a __attribute__((reqd_work_group_size)) - // attribute, check to see if the last argument can be evenly divided - // by the [[intel::num_simd_work_items()]] attribute in SYCL mode. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); @@ -3306,12 +3300,6 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, // __attribute__((reqd_work_group_size)) attribute behaves the // OpenCL way in OpenCL mode (using the OpenCL semantics) and // the SYCL way in SYCL mode (using the SYCL semantics). - // If the declaration has a __attribute__((reqd_work_group_size)) - // attribute, check to see if the first argument can be evenly divided - // by the [[intel::num_simd_work_items()]] attribute in OpenCL mode. - // If the declaration has a __attribute__((reqd_work_group_size)) - // attribute, check to see if the last argument can be evenly divided - // by the [[intel::num_simd_work_items()]] attribute in SYCL mode. if (const auto *DeclAttr = D->getAttr()) { Expr *XDimExpr = DeclAttr->getXDim(); Expr *YDimExpr = DeclAttr->getYDim(); From 9526b187a37c9b5c123dd52e48d021cd078edead Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Fri, 14 May 2021 12:21:00 -0700 Subject: [PATCH 20/20] Address review comments Signed-off-by: Soumi Manna --- clang/include/clang/Basic/AttrDocs.td | 10 +++++----- clang/lib/Sema/SemaDeclAttr.cpp | 27 ++++++++++++--------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 46a4915511304..e75eb8e9be1b3 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2503,6 +2503,11 @@ device kernel, the attribute is not ignored and it is propagated to the kernel. [[intel::num_simd_work_items(N)]] void operator()() const {} }; +If the ``reqd_work_group_size`` attribute is specified on a declaration along +with ``num_simd_work_items``, the required work group size specified +by ``num_simd_work_items`` attribute must evenly divide the index that +increments fastest in the ``reqd_work_group_size`` attribute. + The arguments to ``reqd_work_group_size`` are ordered based on which index increments the fastest. In OpenCL, the first argument is the index that increments the fastest, and in SYCL, the last argument is the index that @@ -2515,11 +2520,6 @@ form, the last (or only) argument is the index that increments fastest. The number of arguments passed to the attribute must match the dimensionality of the kernel the attribute is applied to. -If the ``reqd_work_group_size`` attribute is specified on a declaration along -with ``num_simd_work_items``, the required work group size specified -by ``num_simd_work_items`` attribute must evenly divide the index that -increments fastest in the ``reqd_work_group_size`` attribute. - .. code-block:: c++ // Note, '64' is evenly divisible by '4'; in SYCL, the last diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e48794168ae0a..a4f8d0a8ce2b6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3086,14 +3086,10 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { return; ZDimExpr = ZDim.get(); - // If the declaration has a [[intel::reqd_work_group_size()]] - // or [[cl::reqd_work_group_size()]] attribute, check to see - // if the last argument can be evenly divided by the - // [[intel::num_simd_work_items()]] attribute. - // - // __attribute__((reqd_work_group_size)) attribute behaves the - // OpenCL way in OpenCL mode (using the OpenCL semantics) and - // the SYCL way in SYCL mode (using the SYCL semantics). + // If the num_simd_work_items attribute is specified on a declaration it + // must evenly divide the index that increments fastest in the + // reqd_work_group_size attribute. In OpenCL, the first argument increments + // the fastest, and in SYCL, the last argument increments the fastest. if (const auto *A = D->getAttr()) { int64_t NumSimdWorkItems = A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue(); @@ -3292,14 +3288,15 @@ void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, } } - // If the declaration has a [[intel::reqd_work_group_size()]] - // or [[cl::reqd_work_group_size()]] attribute, check to see - // if the last argument can be evenly divided by the - // [[intel::num_simd_work_items()]] attribute. + // If the reqd_work_group_size attribute is specified on a declaration + // along with num_simd_work_items, the required work group size specified + // by num_simd_work_items attribute must evenly divide the index that + // increments fastest in the reqd_work_group_size attribute. // - // __attribute__((reqd_work_group_size)) attribute behaves the - // OpenCL way in OpenCL mode (using the OpenCL semantics) and - // the SYCL way in SYCL mode (using the SYCL semantics). + // The arguments to reqd_work_group_size are ordered based on which index + // increments the fastest. In OpenCL, the first argument is the index that + // increments the fastest, and in SYCL, the last argument is the index that + // increments the fastest. if (const auto *DeclAttr = D->getAttr()) { Expr *XDimExpr = DeclAttr->getXDim(); Expr *YDimExpr = DeclAttr->getYDim();