From 7f6d8762e2ad3cc3e0c9f3374a3a2ae928bae5e1 Mon Sep 17 00:00:00 2001 From: Denis Bakhvalov Date: Thu, 22 Apr 2021 19:53:14 -0700 Subject: [PATCH 1/6] [ESIMD] Add support for widening SIMT functions - FE part This patch is one of the few patches to provide a functionality to reuse existing scalar function implementations in a vector context. For example, based on scalar version of `float cos(float)`, implement simd cos(simd) - "widened" version of the original scalar function. To achieve that, we mark such functions with `sycl_esimd_widen` attribute which will be later used by vector compiler backend to widen it. For now, this functionality will be used only in internal implementation of specific public ESIMD APIs. It is not supposed to be used directly in the user code. It is a temporary solution to enable ESIMD math functions by reusing existing scalar implementations. Later it is supposed to be replaced by a more generic mechanism. --- clang/include/clang/Basic/Attr.td | 17 +++++++++++ .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/CodeGen/CGSYCLRuntime.cpp | 4 +++ clang/lib/Sema/SemaDeclAttr.cpp | 24 ++++++++++++++++ .../test/CodeGenSYCL/esimd_widen_metadata.cpp | 13 +++++++++ clang/test/SemaSYCL/esimd_widen.cpp | 28 +++++++++++++++++++ 6 files changed, 88 insertions(+) create mode 100644 clang/test/CodeGenSYCL/esimd_widen_metadata.cpp create mode 100644 clang/test/SemaSYCL/esimd_widen.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 66eb9a3fdb10f..c7ad35512cfc7 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1239,6 +1239,23 @@ def SYCLSimdAccessorPtr : InheritableAttr { let Documentation = [Undocumented]; } +// The attribute denotes that it is a function written in SIMT fashion, which +// is used in ESIMD context and needs to be widened by a vector backend compiler. +// For now, this attribute will be used only in internal implementation of +// specific public ESIMD APIs. It is not supposed to be used directly in the +// user code, hence it is undocumented. +// The argument of the attribute specifies the number of SIMD lanes, for which +// the function should be widened. +def SYCLIntelESimdWiden : InheritableAttr { + let Spellings = [GNU<"sycl_esimd_widen">, CXX11<"intel", "sycl_esimd_widen">]; + let Args = [UnsignedArgument<"Number">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let LangOpts = [SYCLIsDevice]; + let Documentation = [Undocumented]; + let SupportsNonconformingLambdaSyntax = 1; + let PragmaAttributeSupport = 0; +} + def SYCLScope : Attr { // No spelling, as this attribute can't be created in the source code. let Spellings = []; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 15dc631014d7f..0b5343025aaf4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11230,6 +11230,8 @@ def err_esimd_global_in_sycl_context : Error< "ESIMD globals cannot be used in a SYCL context">; def err_sycl_device_function_is_called_from_esimd : Error< "SYCL device function cannot be called from an ESIMD context">; +def err_sycl_esimd_widen_unsupported_value : Error< + "%0 attribute argument must be 8, 16, or 32">; def err_nullptr_t_type_in_sycl_kernel : Error<"%0 is an invalid kernel name, " "'std::nullptr_t' is declared in the 'std' namespace ">; diff --git a/clang/lib/CodeGen/CGSYCLRuntime.cpp b/clang/lib/CodeGen/CGSYCLRuntime.cpp index 1cdf825838547..688933b2d9fd1 100644 --- a/clang/lib/CodeGen/CGSYCLRuntime.cpp +++ b/clang/lib/CodeGen/CGSYCLRuntime.cpp @@ -64,6 +64,10 @@ bool CGSYCLRuntime::actOnFunctionStart(const FunctionDecl &FD, if (FD.hasAttr()) F.setMetadata("sycl_explicit_simd", llvm::MDNode::get(F.getContext(), {})); + // Set the function attribute expected by the vector backend compiler. + if (const SYCLIntelESimdWidenAttr *A = FD.getAttr()) + F.addFnAttr("CMGenxSIMT", std::to_string(A->getNumber())); + SYCLScopeAttr *Scope = FD.getAttr(); if (!Scope) return false; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e5bab0ceef73e..baad6b3e784df 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5087,6 +5087,27 @@ static void handleSYCLRegisterNumAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) SYCLRegisterNumAttr(S.Context, AL, RegNo)); } +static void handleSYCLIntelESimdWidenAttrAttr(Sema &S, Decl *D, + const ParsedAttr &Attr) { + uint32_t NumSimdLanes = 0; + const Expr *E = Attr.getArgAsExpr(0); + if (!checkUInt32Argument(S, Attr, E, NumSimdLanes, 0, + /*StrictlyUnsigned=*/true)) + return; + + if (NumSimdLanes != 8 && NumSimdLanes != 16 && NumSimdLanes != 32) { + S.Diag(Attr.getLoc(), diag::err_sycl_esimd_widen_unsupported_value) + << Attr << E->getSourceRange(); + return; + } + + if (D->getAttr()) + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr; + else + D->addAttr(::new (S.Context) + SYCLIntelESimdWidenAttr(S.Context, Attr, NumSimdLanes)); +} + static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *VD = cast(D); if (VD->hasLocalStorage()) { @@ -9107,6 +9128,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_SYCLRegisterNum: handleSYCLRegisterNumAttr(S, D, AL); break; + case ParsedAttr::AT_SYCLIntelESimdWiden: + handleSYCLIntelESimdWidenAttrAttr(S, D, AL); + break; case ParsedAttr::AT_Format: handleFormatAttr(S, D, AL); break; diff --git a/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp b/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp new file mode 100644 index 0000000000000..2afee33832cbc --- /dev/null +++ b/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -disable-llvm-passes -triple spir64-unknown-unknown-sycldevice \ +// RUN: -fsycl-is-device -S -emit-llvm %s -o - | FileCheck %s + +// This test checks the generation of CMGenxSIMT function attributes + +__attribute__((sycl_device)) __attribute__((sycl_esimd_widen(32))) void foo1() {} +// CHECK: @_Z4foo1v() #[[ATTR1:[0-9]+]] + +__attribute__((sycl_device)) __attribute__((sycl_esimd_widen(8))) __attribute__((sycl_esimd_widen(16))) void foo2() {} +// CHECK: @_Z4foo2v() #[[ATTR2:[0-9]+]] + +// CHECK: attributes #[[ATTR1]] = { {{.*}} "CMGenxSIMT"="32" {{.*}}} +// CHECK: attributes #[[ATTR2]] = { {{.*}} "CMGenxSIMT"="8" {{.*}}} diff --git a/clang/test/SemaSYCL/esimd_widen.cpp b/clang/test/SemaSYCL/esimd_widen.cpp new file mode 100644 index 0000000000000..498dc1bf852d7 --- /dev/null +++ b/clang/test/SemaSYCL/esimd_widen.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s + +// This test check the semantics of sycl_esimd_widen attribute + +// expected-error@+1{{'sycl_esimd_widen' attribute argument must be 8, 16, or 32}} +__attribute__((sycl_esimd_widen(17))) void foo1() {} +// expected-warning@+1{{attribute 'sycl_esimd_widen' is already applied with different arguments}} +__attribute__((sycl_esimd_widen(8))) __attribute__((sycl_esimd_widen(16))) void foo2() {} + +__attribute__((sycl_esimd_widen(8))) void foo3() {} +__attribute__((sycl_esimd_widen(16))) void foo4() {} +__attribute__((sycl_esimd_widen(32))) void foo5() {} +[[intel::sycl_esimd_widen(8)]] void foo6() {} + +class A { + __attribute__((sycl_esimd_widen(8))) void func1() {} + [[intel::sycl_esimd_widen(8)]] void func2() {} +}; + +struct Functor { + void operator()(int) const __attribute__((sycl_esimd_widen(8))) {} + [[intel::sycl_esimd_widen(8)]] void operator()(float) const {} +}; + +void test() { + auto f1 = []() __attribute__((sycl_esimd_widen(8))){}; + auto f2 = []() [[intel::sycl_esimd_widen(8)]]{}; +} From 342f0068911de5d822ff449de5f3d0acb8eb0b87 Mon Sep 17 00:00:00 2001 From: Denis Bakhvalov Date: Fri, 23 Apr 2021 14:50:45 -0700 Subject: [PATCH 2/6] Addressed review comments --- clang/include/clang/Basic/Attr.td | 4 +- clang/include/clang/Sema/Sema.h | 4 + clang/lib/CodeGen/CGSYCLRuntime.cpp | 8 +- clang/lib/Sema/SemaDecl.cpp | 2 + clang/lib/Sema/SemaDeclAttr.cpp | 83 +++++++++++++++---- .../test/CodeGenSYCL/esimd_widen_metadata.cpp | 9 +- .../test/SemaSYCL/esimd-widen-attr-device.cpp | 45 ++++++++++ clang/test/SemaSYCL/esimd-widen-attr-host.cpp | 9 ++ clang/test/SemaSYCL/esimd_widen.cpp | 28 ------- 9 files changed, 141 insertions(+), 51 deletions(-) create mode 100644 clang/test/SemaSYCL/esimd-widen-attr-device.cpp create mode 100644 clang/test/SemaSYCL/esimd-widen-attr-host.cpp delete mode 100644 clang/test/SemaSYCL/esimd_widen.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index c7ad35512cfc7..d603a2cf3df46 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1247,8 +1247,8 @@ def SYCLSimdAccessorPtr : InheritableAttr { // The argument of the attribute specifies the number of SIMD lanes, for which // the function should be widened. def SYCLIntelESimdWiden : InheritableAttr { - let Spellings = [GNU<"sycl_esimd_widen">, CXX11<"intel", "sycl_esimd_widen">]; - let Args = [UnsignedArgument<"Number">]; + let Spellings = [CXX11<"intel", "sycl_esimd_widen">]; + let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[Function], ErrorDiag>; let LangOpts = [SYCLIsDevice]; let Documentation = [Undocumented]; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f1414c3af6e6a..8583528e1ea4b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10282,6 +10282,10 @@ class Sema final { SYCLIntelNumSimdWorkItemsAttr * MergeSYCLIntelNumSimdWorkItemsAttr(Decl *D, const SYCLIntelNumSimdWorkItemsAttr &A); + void AddSYCLIntelESimdWidenAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *E); + SYCLIntelESimdWidenAttr * + MergeSYCLIntelESimdWidenAttr(Decl *D, const SYCLIntelESimdWidenAttr &A); void AddSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E); diff --git a/clang/lib/CodeGen/CGSYCLRuntime.cpp b/clang/lib/CodeGen/CGSYCLRuntime.cpp index 688933b2d9fd1..2fec9de80acd4 100644 --- a/clang/lib/CodeGen/CGSYCLRuntime.cpp +++ b/clang/lib/CodeGen/CGSYCLRuntime.cpp @@ -65,8 +65,12 @@ bool CGSYCLRuntime::actOnFunctionStart(const FunctionDecl &FD, F.setMetadata("sycl_explicit_simd", llvm::MDNode::get(F.getContext(), {})); // Set the function attribute expected by the vector backend compiler. - if (const SYCLIntelESimdWidenAttr *A = FD.getAttr()) - F.addFnAttr("CMGenxSIMT", std::to_string(A->getNumber())); + if (const auto *A = FD.getAttr()) + if (const auto *DeclExpr = dyn_cast(A->getValue())) { + SmallString<2> Str; + DeclExpr->getResultAsAPSInt().toString(Str); + F.addFnAttr("CMGenxSIMT", Str); + } SYCLScopeAttr *Scope = FD.getAttr(); if (!Scope) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fd832859189f2..7ff0b2c8dd041 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2627,6 +2627,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, NewAttr = S.MergeIntelNamedSubGroupSizeAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) NewAttr = S.MergeSYCLIntelNumSimdWorkItemsAttr(D, *A); + else if (const auto *A = dyn_cast(Attr)) + NewAttr = S.MergeSYCLIntelESimdWidenAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) NewAttr = S.MergeSYCLIntelSchedulerTargetFmaxMhzAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index baad6b3e784df..ef5b68b501e75 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5087,25 +5087,74 @@ static void handleSYCLRegisterNumAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) SYCLRegisterNumAttr(S.Context, AL, RegNo)); } -static void handleSYCLIntelESimdWidenAttrAttr(Sema &S, Decl *D, - const ParsedAttr &Attr) { - uint32_t NumSimdLanes = 0; - const Expr *E = Attr.getArgAsExpr(0); - if (!checkUInt32Argument(S, Attr, E, NumSimdLanes, 0, - /*StrictlyUnsigned=*/true)) - return; +void Sema::AddSYCLIntelESimdWidenAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *E) { + if (!E->isValueDependent()) { + // Validate that we have an integer constant expression and then store the + // converted constant expression into the semantic attribute so that we + // don't have to evaluate it again later. + llvm::APSInt ArgVal; + ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal); + if (Res.isInvalid()) + return; + E = Res.get(); - if (NumSimdLanes != 8 && NumSimdLanes != 16 && NumSimdLanes != 32) { - S.Diag(Attr.getLoc(), diag::err_sycl_esimd_widen_unsupported_value) - << Attr << E->getSourceRange(); - return; + // This attribute requires a strictly positive value. + if (ArgVal <= 0) { + Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) + << CI << /*positive*/ 0; + return; + } + if (ArgVal != 8 && ArgVal != 16 && ArgVal != 32) { + Diag(E->getExprLoc(), diag::err_sycl_esimd_widen_unsupported_value) << CI; + return; + } + + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + // If the other attribute argument is instantiation dependent, we won't + // have converted it to a constant expression yet and thus we test + // whether this is a null pointer. + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (ArgVal != DeclExpr->getResultAsAPSInt()) { + Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI; + Diag(DeclAttr->getLoc(), diag::note_previous_attribute); + } + // Drop the duplicate attribute. + return; + } + } } - if (D->getAttr()) - S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr; - else - D->addAttr(::new (S.Context) - SYCLIntelESimdWidenAttr(S.Context, Attr, NumSimdLanes)); + D->addAttr(::new (Context) SYCLIntelESimdWidenAttr(Context, CI, E)); +} + +SYCLIntelESimdWidenAttr * +Sema::MergeSYCLIntelESimdWidenAttr(Decl *D, const SYCLIntelESimdWidenAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { + if (const auto *MergeExpr = dyn_cast(A.getValue())) { + if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + } + // Do not add a duplicate attribute. + return nullptr; + } + } + } + return ::new (Context) SYCLIntelESimdWidenAttr(Context, A, A.getValue()); +} + +static void handleSYCLIntelESimdWidenAttr(Sema &S, Decl *D, + const ParsedAttr &A) { + S.CheckDeprecatedSYCLAttributeSpelling(A); + + Expr *E = A.getArgAsExpr(0); + S.AddSYCLIntelESimdWidenAttr(D, A, E); } static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -9129,7 +9178,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSYCLRegisterNumAttr(S, D, AL); break; case ParsedAttr::AT_SYCLIntelESimdWiden: - handleSYCLIntelESimdWidenAttrAttr(S, D, AL); + handleSYCLIntelESimdWidenAttr(S, D, AL); break; case ParsedAttr::AT_Format: handleFormatAttr(S, D, AL); diff --git a/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp b/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp index 2afee33832cbc..5d65ca272ead3 100644 --- a/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp +++ b/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp @@ -3,11 +3,16 @@ // This test checks the generation of CMGenxSIMT function attributes -__attribute__((sycl_device)) __attribute__((sycl_esimd_widen(32))) void foo1() {} +[[intel::sycl_esimd_widen(32)]] __attribute__((sycl_device)) void foo1() {} // CHECK: @_Z4foo1v() #[[ATTR1:[0-9]+]] -__attribute__((sycl_device)) __attribute__((sycl_esimd_widen(8))) __attribute__((sycl_esimd_widen(16))) void foo2() {} +[[intel::sycl_esimd_widen(8)]] [[intel::sycl_esimd_widen(16)]] __attribute__((sycl_device)) void foo2() {} // CHECK: @_Z4foo2v() #[[ATTR2:[0-9]+]] +[[intel::sycl_esimd_widen(8)]] __attribute__((sycl_device)) void foo3(); +[[intel::sycl_esimd_widen(16)]] __attribute__((sycl_device)) void foo3() {} +// CHECK: @_Z4foo3v() #[[ATTR3:[0-9]+]] + // CHECK: attributes #[[ATTR1]] = { {{.*}} "CMGenxSIMT"="32" {{.*}}} // CHECK: attributes #[[ATTR2]] = { {{.*}} "CMGenxSIMT"="8" {{.*}}} +// CHECK: attributes #[[ATTR3]] = { {{.*}} "CMGenxSIMT"="16" {{.*}}} diff --git a/clang/test/SemaSYCL/esimd-widen-attr-device.cpp b/clang/test/SemaSYCL/esimd-widen-attr-device.cpp new file mode 100644 index 0000000000000..e38db4e33cc44 --- /dev/null +++ b/clang/test/SemaSYCL/esimd-widen-attr-device.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s + +// This test check the semantics of sycl_esimd_widen attribute + +// expected-error@+1{{'sycl_esimd_widen' attribute argument must be 8, 16, or 32}} +[[intel::sycl_esimd_widen(17)]] void foo1() {} +// expected-error@+1{{'sycl_esimd_widen' attribute requires a positive integral compile time constant expression}} +[[intel::sycl_esimd_widen(-8)]] void foo2() {} +// expected-error@+1{{integral constant expression must have integral or unscoped enumeration type, not 'float'}} +[[intel::sycl_esimd_widen(3.f)]] void foo3() {} + +[[intel::sycl_esimd_widen(8)]] void foo4() {} +[[intel::sycl_esimd_widen(16)]] void foo5() {} +[[intel::sycl_esimd_widen(32)]] void foo6() {} + +// expected-warning@+1{{unknown attribute 'sycl_esimd_widen' ignored}} +__attribute__((sycl_esimd_widen(8))) void foo7() {} + +// expected-note@+2{{previous attribute is here}} +// expected-warning@+1{{attribute 'sycl_esimd_widen' is already applied with different arguments}} +[[intel::sycl_esimd_widen(8)]] [[intel::sycl_esimd_widen(16)]] void foo8() {} + +// expected-note@+1{{previous attribute is here}} +[[intel::sycl_esimd_widen(8)]] void foo9(); +// expected-warning@+1{{attribute 'sycl_esimd_widen' is already applied with different arguments}} +[[intel::sycl_esimd_widen(16)]] void foo9() {} + +// No diagnostic is emitted because the arguments match. +[[intel::sycl_esimd_widen(16)]] void foo10(); +[[intel::sycl_esimd_widen(16)]] void foo10() {} + +// expected-error@+1{{'sycl_esimd_widen' attribute only applies to functions}} +[[intel::sycl_esimd_widen(8)]] int glob = 0; + +class A { + [[intel::sycl_esimd_widen(8)]] void func2() {} +}; + +struct Functor { + [[intel::sycl_esimd_widen(8)]] void operator()(float) const {} +}; + +void test() { + auto f2 = []() [[intel::sycl_esimd_widen(8)]]{}; +} diff --git a/clang/test/SemaSYCL/esimd-widen-attr-host.cpp b/clang/test/SemaSYCL/esimd-widen-attr-host.cpp new file mode 100644 index 0000000000000..db20448c7c9d9 --- /dev/null +++ b/clang/test/SemaSYCL/esimd-widen-attr-host.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s + +// This test check the semantics of sycl_esimd_widen attribute + +// expected-warning@+1{{'sycl_esimd_widen' attribute ignored}} +[[intel::sycl_esimd_widen(17)]] void foo1() {} + +// expected-warning@+1{{unknown attribute 'sycl_esimd_widen' ignored}} +__attribute__((sycl_esimd_widen(8))) void foo2() {} \ No newline at end of file diff --git a/clang/test/SemaSYCL/esimd_widen.cpp b/clang/test/SemaSYCL/esimd_widen.cpp deleted file mode 100644 index 498dc1bf852d7..0000000000000 --- a/clang/test/SemaSYCL/esimd_widen.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s - -// This test check the semantics of sycl_esimd_widen attribute - -// expected-error@+1{{'sycl_esimd_widen' attribute argument must be 8, 16, or 32}} -__attribute__((sycl_esimd_widen(17))) void foo1() {} -// expected-warning@+1{{attribute 'sycl_esimd_widen' is already applied with different arguments}} -__attribute__((sycl_esimd_widen(8))) __attribute__((sycl_esimd_widen(16))) void foo2() {} - -__attribute__((sycl_esimd_widen(8))) void foo3() {} -__attribute__((sycl_esimd_widen(16))) void foo4() {} -__attribute__((sycl_esimd_widen(32))) void foo5() {} -[[intel::sycl_esimd_widen(8)]] void foo6() {} - -class A { - __attribute__((sycl_esimd_widen(8))) void func1() {} - [[intel::sycl_esimd_widen(8)]] void func2() {} -}; - -struct Functor { - void operator()(int) const __attribute__((sycl_esimd_widen(8))) {} - [[intel::sycl_esimd_widen(8)]] void operator()(float) const {} -}; - -void test() { - auto f1 = []() __attribute__((sycl_esimd_widen(8))){}; - auto f2 = []() [[intel::sycl_esimd_widen(8)]]{}; -} From c2b2f671f4e1bafb99b84a35dac539a01c260626 Mon Sep 17 00:00:00 2001 From: Denis Bakhvalov Date: Fri, 23 Apr 2021 15:02:26 -0700 Subject: [PATCH 3/6] renamed sycl_esimd_widen into sycl_esimd_vectorize --- clang/include/clang/Basic/Attr.td | 10 ++--- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/include/clang/Sema/Sema.h | 9 ++-- clang/lib/CodeGen/CGSYCLRuntime.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 4 +- clang/lib/Sema/SemaDeclAttr.cpp | 31 +++++++------ ...en_metadata.cpp => esimd-vectorize-md.cpp} | 8 ++-- .../SemaSYCL/esimd-vectorize-attr-device.cpp | 45 +++++++++++++++++++ .../SemaSYCL/esimd-vectorize-attr-host.cpp | 9 ++++ .../test/SemaSYCL/esimd-widen-attr-device.cpp | 45 ------------------- clang/test/SemaSYCL/esimd-widen-attr-host.cpp | 9 ---- 11 files changed, 89 insertions(+), 85 deletions(-) rename clang/test/CodeGenSYCL/{esimd_widen_metadata.cpp => esimd-vectorize-md.cpp} (60%) create mode 100644 clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp create mode 100644 clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp delete mode 100644 clang/test/SemaSYCL/esimd-widen-attr-device.cpp delete mode 100644 clang/test/SemaSYCL/esimd-widen-attr-host.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d603a2cf3df46..4a05eb3b4168f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1239,15 +1239,15 @@ def SYCLSimdAccessorPtr : InheritableAttr { let Documentation = [Undocumented]; } -// The attribute denotes that it is a function written in SIMT fashion, which -// is used in ESIMD context and needs to be widened by a vector backend compiler. +// The attribute denotes that it is a function written in a scalar fashion, which +// is used in ESIMD context and needs to be vectorized by a vector backend compiler. // For now, this attribute will be used only in internal implementation of // specific public ESIMD APIs. It is not supposed to be used directly in the // user code, hence it is undocumented. // The argument of the attribute specifies the number of SIMD lanes, for which -// the function should be widened. -def SYCLIntelESimdWiden : InheritableAttr { - let Spellings = [CXX11<"intel", "sycl_esimd_widen">]; +// the function should be vectorized. +def SYCLIntelESimdVectorize : InheritableAttr { + let Spellings = [CXX11<"intel", "sycl_esimd_vectorize">]; let Args = [ExprArgument<"Value">]; let Subjects = SubjectList<[Function], ErrorDiag>; let LangOpts = [SYCLIsDevice]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0b5343025aaf4..02ad14b6d36ab 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11230,7 +11230,7 @@ def err_esimd_global_in_sycl_context : Error< "ESIMD globals cannot be used in a SYCL context">; def err_sycl_device_function_is_called_from_esimd : Error< "SYCL device function cannot be called from an ESIMD context">; -def err_sycl_esimd_widen_unsupported_value : Error< +def err_sycl_esimd_vectorize_unsupported_value : Error< "%0 attribute argument must be 8, 16, or 32">; def err_nullptr_t_type_in_sycl_kernel : Error<"%0 is an invalid kernel name, " diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8583528e1ea4b..1a40d77537476 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10282,10 +10282,11 @@ class Sema final { SYCLIntelNumSimdWorkItemsAttr * MergeSYCLIntelNumSimdWorkItemsAttr(Decl *D, const SYCLIntelNumSimdWorkItemsAttr &A); - void AddSYCLIntelESimdWidenAttr(Decl *D, const AttributeCommonInfo &CI, - Expr *E); - SYCLIntelESimdWidenAttr * - MergeSYCLIntelESimdWidenAttr(Decl *D, const SYCLIntelESimdWidenAttr &A); + void AddSYCLIntelESimdVectorizeAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *E); + SYCLIntelESimdVectorizeAttr * + MergeSYCLIntelESimdVectorizeAttr(Decl *D, + const SYCLIntelESimdVectorizeAttr &A); void AddSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E); diff --git a/clang/lib/CodeGen/CGSYCLRuntime.cpp b/clang/lib/CodeGen/CGSYCLRuntime.cpp index 2fec9de80acd4..279dd689e5a4a 100644 --- a/clang/lib/CodeGen/CGSYCLRuntime.cpp +++ b/clang/lib/CodeGen/CGSYCLRuntime.cpp @@ -65,7 +65,7 @@ bool CGSYCLRuntime::actOnFunctionStart(const FunctionDecl &FD, F.setMetadata("sycl_explicit_simd", llvm::MDNode::get(F.getContext(), {})); // Set the function attribute expected by the vector backend compiler. - if (const auto *A = FD.getAttr()) + if (const auto *A = FD.getAttr()) if (const auto *DeclExpr = dyn_cast(A->getValue())) { SmallString<2> Str; DeclExpr->getResultAsAPSInt().toString(Str); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7ff0b2c8dd041..4569d408f327b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2627,8 +2627,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, NewAttr = S.MergeIntelNamedSubGroupSizeAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) NewAttr = S.MergeSYCLIntelNumSimdWorkItemsAttr(D, *A); - else if (const auto *A = dyn_cast(Attr)) - NewAttr = S.MergeSYCLIntelESimdWidenAttr(D, *A); + else if (const auto *A = dyn_cast(Attr)) + NewAttr = S.MergeSYCLIntelESimdVectorizeAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) NewAttr = S.MergeSYCLIntelSchedulerTargetFmaxMhzAttr(D, *A); else if (const auto *A = dyn_cast(Attr)) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ef5b68b501e75..9c754ebc528c2 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5087,8 +5087,9 @@ static void handleSYCLRegisterNumAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) SYCLRegisterNumAttr(S.Context, AL, RegNo)); } -void Sema::AddSYCLIntelESimdWidenAttr(Decl *D, const AttributeCommonInfo &CI, - Expr *E) { +void Sema::AddSYCLIntelESimdVectorizeAttr(Decl *D, + const AttributeCommonInfo &CI, + Expr *E) { if (!E->isValueDependent()) { // Validate that we have an integer constant expression and then store the // converted constant expression into the semantic attribute so that we @@ -5106,13 +5107,14 @@ void Sema::AddSYCLIntelESimdWidenAttr(Decl *D, const AttributeCommonInfo &CI, return; } if (ArgVal != 8 && ArgVal != 16 && ArgVal != 32) { - Diag(E->getExprLoc(), diag::err_sycl_esimd_widen_unsupported_value) << CI; + Diag(E->getExprLoc(), diag::err_sycl_esimd_vectorize_unsupported_value) + << CI; return; } // Check to see if there's a duplicate attribute with different values // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclAttr = D->getAttr()) { // If the other attribute argument is instantiation dependent, we won't // have converted it to a constant expression yet and thus we test // whether this is a null pointer. @@ -5127,14 +5129,15 @@ void Sema::AddSYCLIntelESimdWidenAttr(Decl *D, const AttributeCommonInfo &CI, } } - D->addAttr(::new (Context) SYCLIntelESimdWidenAttr(Context, CI, E)); + D->addAttr(::new (Context) SYCLIntelESimdVectorizeAttr(Context, CI, E)); } -SYCLIntelESimdWidenAttr * -Sema::MergeSYCLIntelESimdWidenAttr(Decl *D, const SYCLIntelESimdWidenAttr &A) { +SYCLIntelESimdVectorizeAttr * +Sema::MergeSYCLIntelESimdVectorizeAttr(Decl *D, + const SYCLIntelESimdVectorizeAttr &A) { // Check to see if there's a duplicate attribute with different values // already applied to the declaration. - if (const auto *DeclAttr = D->getAttr()) { + if (const auto *DeclAttr = D->getAttr()) { if (const auto *DeclExpr = dyn_cast(DeclAttr->getValue())) { if (const auto *MergeExpr = dyn_cast(A.getValue())) { if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { @@ -5146,15 +5149,15 @@ Sema::MergeSYCLIntelESimdWidenAttr(Decl *D, const SYCLIntelESimdWidenAttr &A) { } } } - return ::new (Context) SYCLIntelESimdWidenAttr(Context, A, A.getValue()); + return ::new (Context) SYCLIntelESimdVectorizeAttr(Context, A, A.getValue()); } -static void handleSYCLIntelESimdWidenAttr(Sema &S, Decl *D, - const ParsedAttr &A) { +static void handleSYCLIntelESimdVectorizeAttr(Sema &S, Decl *D, + const ParsedAttr &A) { S.CheckDeprecatedSYCLAttributeSpelling(A); Expr *E = A.getArgAsExpr(0); - S.AddSYCLIntelESimdWidenAttr(D, A, E); + S.AddSYCLIntelESimdVectorizeAttr(D, A, E); } static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -9177,8 +9180,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_SYCLRegisterNum: handleSYCLRegisterNumAttr(S, D, AL); break; - case ParsedAttr::AT_SYCLIntelESimdWiden: - handleSYCLIntelESimdWidenAttr(S, D, AL); + case ParsedAttr::AT_SYCLIntelESimdVectorize: + handleSYCLIntelESimdVectorizeAttr(S, D, AL); break; case ParsedAttr::AT_Format: handleFormatAttr(S, D, AL); diff --git a/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp b/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp similarity index 60% rename from clang/test/CodeGenSYCL/esimd_widen_metadata.cpp rename to clang/test/CodeGenSYCL/esimd-vectorize-md.cpp index 5d65ca272ead3..1446e4e94122d 100644 --- a/clang/test/CodeGenSYCL/esimd_widen_metadata.cpp +++ b/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp @@ -3,14 +3,14 @@ // This test checks the generation of CMGenxSIMT function attributes -[[intel::sycl_esimd_widen(32)]] __attribute__((sycl_device)) void foo1() {} +[[intel::sycl_esimd_vectorize(32)]] __attribute__((sycl_device)) void foo1() {} // CHECK: @_Z4foo1v() #[[ATTR1:[0-9]+]] -[[intel::sycl_esimd_widen(8)]] [[intel::sycl_esimd_widen(16)]] __attribute__((sycl_device)) void foo2() {} +[[intel::sycl_esimd_vectorize(8)]] [[intel::sycl_esimd_vectorize(16)]] __attribute__((sycl_device)) void foo2() {} // CHECK: @_Z4foo2v() #[[ATTR2:[0-9]+]] -[[intel::sycl_esimd_widen(8)]] __attribute__((sycl_device)) void foo3(); -[[intel::sycl_esimd_widen(16)]] __attribute__((sycl_device)) void foo3() {} +[[intel::sycl_esimd_vectorize(8)]] __attribute__((sycl_device)) void foo3(); +[[intel::sycl_esimd_vectorize(16)]] __attribute__((sycl_device)) void foo3() {} // CHECK: @_Z4foo3v() #[[ATTR3:[0-9]+]] // CHECK: attributes #[[ATTR1]] = { {{.*}} "CMGenxSIMT"="32" {{.*}}} diff --git a/clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp b/clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp new file mode 100644 index 0000000000000..07978725eb4ff --- /dev/null +++ b/clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s + +// This test check the semantics of sycl_esimd_vectorize attribute + +// expected-error@+1{{'sycl_esimd_vectorize' attribute argument must be 8, 16, or 32}} +[[intel::sycl_esimd_vectorize(17)]] void foo1() {} +// expected-error@+1{{'sycl_esimd_vectorize' attribute requires a positive integral compile time constant expression}} +[[intel::sycl_esimd_vectorize(-8)]] void foo2() {} +// expected-error@+1{{integral constant expression must have integral or unscoped enumeration type, not 'float'}} +[[intel::sycl_esimd_vectorize(3.f)]] void foo3() {} + +[[intel::sycl_esimd_vectorize(8)]] void foo4() {} +[[intel::sycl_esimd_vectorize(16)]] void foo5() {} +[[intel::sycl_esimd_vectorize(32)]] void foo6() {} + +// expected-warning@+1{{unknown attribute 'sycl_esimd_vectorize' ignored}} +__attribute__((sycl_esimd_vectorize(8))) void foo7() {} + +// expected-note@+2{{previous attribute is here}} +// expected-warning@+1{{attribute 'sycl_esimd_vectorize' is already applied with different arguments}} +[[intel::sycl_esimd_vectorize(8)]] [[intel::sycl_esimd_vectorize(16)]] void foo8() {} + +// expected-note@+1{{previous attribute is here}} +[[intel::sycl_esimd_vectorize(8)]] void foo9(); +// expected-warning@+1{{attribute 'sycl_esimd_vectorize' is already applied with different arguments}} +[[intel::sycl_esimd_vectorize(16)]] void foo9() {} + +// No diagnostic is emitted because the arguments match. +[[intel::sycl_esimd_vectorize(16)]] void foo10(); +[[intel::sycl_esimd_vectorize(16)]] void foo10() {} + +// expected-error@+1{{'sycl_esimd_vectorize' attribute only applies to functions}} +[[intel::sycl_esimd_vectorize(8)]] int glob = 0; + +class A { + [[intel::sycl_esimd_vectorize(8)]] void func2() {} +}; + +struct Functor { + [[intel::sycl_esimd_vectorize(8)]] void operator()(float) const {} +}; + +void test() { + auto f2 = []() [[intel::sycl_esimd_vectorize(8)]]{}; +} diff --git a/clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp b/clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp new file mode 100644 index 0000000000000..aaed234de7db5 --- /dev/null +++ b/clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s + +// This test check the semantics of sycl_esimd_vectorize attribute + +// expected-warning@+1{{'sycl_esimd_vectorize' attribute ignored}} +[[intel::sycl_esimd_vectorize(17)]] void foo1() {} + +// expected-warning@+1{{unknown attribute 'sycl_esimd_vectorize' ignored}} +__attribute__((sycl_esimd_vectorize(8))) void foo2() {} \ No newline at end of file diff --git a/clang/test/SemaSYCL/esimd-widen-attr-device.cpp b/clang/test/SemaSYCL/esimd-widen-attr-device.cpp deleted file mode 100644 index e38db4e33cc44..0000000000000 --- a/clang/test/SemaSYCL/esimd-widen-attr-device.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s - -// This test check the semantics of sycl_esimd_widen attribute - -// expected-error@+1{{'sycl_esimd_widen' attribute argument must be 8, 16, or 32}} -[[intel::sycl_esimd_widen(17)]] void foo1() {} -// expected-error@+1{{'sycl_esimd_widen' attribute requires a positive integral compile time constant expression}} -[[intel::sycl_esimd_widen(-8)]] void foo2() {} -// expected-error@+1{{integral constant expression must have integral or unscoped enumeration type, not 'float'}} -[[intel::sycl_esimd_widen(3.f)]] void foo3() {} - -[[intel::sycl_esimd_widen(8)]] void foo4() {} -[[intel::sycl_esimd_widen(16)]] void foo5() {} -[[intel::sycl_esimd_widen(32)]] void foo6() {} - -// expected-warning@+1{{unknown attribute 'sycl_esimd_widen' ignored}} -__attribute__((sycl_esimd_widen(8))) void foo7() {} - -// expected-note@+2{{previous attribute is here}} -// expected-warning@+1{{attribute 'sycl_esimd_widen' is already applied with different arguments}} -[[intel::sycl_esimd_widen(8)]] [[intel::sycl_esimd_widen(16)]] void foo8() {} - -// expected-note@+1{{previous attribute is here}} -[[intel::sycl_esimd_widen(8)]] void foo9(); -// expected-warning@+1{{attribute 'sycl_esimd_widen' is already applied with different arguments}} -[[intel::sycl_esimd_widen(16)]] void foo9() {} - -// No diagnostic is emitted because the arguments match. -[[intel::sycl_esimd_widen(16)]] void foo10(); -[[intel::sycl_esimd_widen(16)]] void foo10() {} - -// expected-error@+1{{'sycl_esimd_widen' attribute only applies to functions}} -[[intel::sycl_esimd_widen(8)]] int glob = 0; - -class A { - [[intel::sycl_esimd_widen(8)]] void func2() {} -}; - -struct Functor { - [[intel::sycl_esimd_widen(8)]] void operator()(float) const {} -}; - -void test() { - auto f2 = []() [[intel::sycl_esimd_widen(8)]]{}; -} diff --git a/clang/test/SemaSYCL/esimd-widen-attr-host.cpp b/clang/test/SemaSYCL/esimd-widen-attr-host.cpp deleted file mode 100644 index db20448c7c9d9..0000000000000 --- a/clang/test/SemaSYCL/esimd-widen-attr-host.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: %clang_cc1 -fsycl-is-host -fsyntax-only -verify %s - -// This test check the semantics of sycl_esimd_widen attribute - -// expected-warning@+1{{'sycl_esimd_widen' attribute ignored}} -[[intel::sycl_esimd_widen(17)]] void foo1() {} - -// expected-warning@+1{{unknown attribute 'sycl_esimd_widen' ignored}} -__attribute__((sycl_esimd_widen(8))) void foo2() {} \ No newline at end of file From fa776468b189202ba761dfe81a10818f74170c44 Mon Sep 17 00:00:00 2001 From: Denis Bakhvalov Date: Wed, 28 Apr 2021 14:45:36 -0700 Subject: [PATCH 4/6] Addressed review comments --- clang/lib/CodeGen/CGSYCLRuntime.cpp | 2 +- clang/lib/Sema/SemaDeclAttr.cpp | 6 -- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 16 ++++ .../SemaSYCL/esimd-vectorize-attr-device.cpp | 7 +- .../SemaSYCL/esimd-vectorize-attr-host.cpp | 4 +- ...l-device-sycl_esimd_vectorize-template.cpp | 95 +++++++++++++++++++ 6 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 clang/test/SemaSYCL/sycl-device-sycl_esimd_vectorize-template.cpp diff --git a/clang/lib/CodeGen/CGSYCLRuntime.cpp b/clang/lib/CodeGen/CGSYCLRuntime.cpp index 279dd689e5a4a..d1af26a9c4d7e 100644 --- a/clang/lib/CodeGen/CGSYCLRuntime.cpp +++ b/clang/lib/CodeGen/CGSYCLRuntime.cpp @@ -66,7 +66,7 @@ bool CGSYCLRuntime::actOnFunctionStart(const FunctionDecl &FD, // Set the function attribute expected by the vector backend compiler. if (const auto *A = FD.getAttr()) - if (const auto *DeclExpr = dyn_cast(A->getValue())) { + if (const auto *DeclExpr = cast(A->getValue())) { SmallString<2> Str; DeclExpr->getResultAsAPSInt().toString(Str); F.addFnAttr("CMGenxSIMT", Str); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 9c754ebc528c2..548fa364d08d9 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5100,12 +5100,6 @@ void Sema::AddSYCLIntelESimdVectorizeAttr(Decl *D, return; E = Res.get(); - // This attribute requires a strictly positive value. - if (ArgVal <= 0) { - Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) - << CI << /*positive*/ 0; - return; - } if (ArgVal != 8 && ArgVal != 16 && ArgVal != 32) { Diag(E->getExprLoc(), diag::err_sycl_esimd_vectorize_unsupported_value) << CI; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5effaaf5a3d58..51e274ee6adc0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -733,6 +733,16 @@ static void instantiateSYCLIntelFPGAInitiationIntervalAttr( S.AddSYCLIntelFPGAInitiationIntervalAttr(New, *A, Result.getAs()); } +static void instantiateSYCLIntelESimdVectorizeAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const SYCLIntelESimdVectorizeAttr *A, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult Result = S.SubstExpr(A->getValue(), TemplateArgs); + if (!Result.isInvalid()) + S.AddSYCLIntelESimdVectorizeAttr(New, *A, Result.getAs()); +} + /// Determine whether the attribute A might be relevent to the declaration D. /// If not, we can skip instantiating it. The attribute may or may not have /// been instantiated yet. @@ -970,6 +980,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, *this, TemplateArgs, SYCLIntelFPGAInitiationInterval, New); continue; } + if (const auto *SYCLIntelESimdVectorize = + dyn_cast(TmplAttr)) { + instantiateSYCLIntelESimdVectorizeAttr(*this, TemplateArgs, + SYCLIntelESimdVectorize, New); + continue; + } // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { diff --git a/clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp b/clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp index 07978725eb4ff..e15cb67c980e7 100644 --- a/clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp +++ b/clang/test/SemaSYCL/esimd-vectorize-attr-device.cpp @@ -4,8 +4,6 @@ // expected-error@+1{{'sycl_esimd_vectorize' attribute argument must be 8, 16, or 32}} [[intel::sycl_esimd_vectorize(17)]] void foo1() {} -// expected-error@+1{{'sycl_esimd_vectorize' attribute requires a positive integral compile time constant expression}} -[[intel::sycl_esimd_vectorize(-8)]] void foo2() {} // expected-error@+1{{integral constant expression must have integral or unscoped enumeration type, not 'float'}} [[intel::sycl_esimd_vectorize(3.f)]] void foo3() {} @@ -13,6 +11,8 @@ [[intel::sycl_esimd_vectorize(16)]] void foo5() {} [[intel::sycl_esimd_vectorize(32)]] void foo6() {} +// We explicitly do not support a GNU spelling for this attribute, which is why it is +// treated as an unknown attribute. // expected-warning@+1{{unknown attribute 'sycl_esimd_vectorize' ignored}} __attribute__((sycl_esimd_vectorize(8))) void foo7() {} @@ -43,3 +43,6 @@ struct Functor { void test() { auto f2 = []() [[intel::sycl_esimd_vectorize(8)]]{}; } + +template +[[intel::sycl_esimd_vectorize(N)]] void templateFunc(); diff --git a/clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp b/clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp index aaed234de7db5..dbb4a7b81501d 100644 --- a/clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp +++ b/clang/test/SemaSYCL/esimd-vectorize-attr-host.cpp @@ -5,5 +5,7 @@ // expected-warning@+1{{'sycl_esimd_vectorize' attribute ignored}} [[intel::sycl_esimd_vectorize(17)]] void foo1() {} +// We explicitly do not support a GNU spelling for this attribute, which is why it is +// treated as an unknown attribute. // expected-warning@+1{{unknown attribute 'sycl_esimd_vectorize' ignored}} -__attribute__((sycl_esimd_vectorize(8))) void foo2() {} \ No newline at end of file +__attribute__((sycl_esimd_vectorize(8))) void foo2() {} diff --git a/clang/test/SemaSYCL/sycl-device-sycl_esimd_vectorize-template.cpp b/clang/test/SemaSYCL/sycl-device-sycl_esimd_vectorize-template.cpp new file mode 100644 index 0000000000000..bf9fbde4e443d --- /dev/null +++ b/clang/test/SemaSYCL/sycl-device-sycl_esimd_vectorize-template.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s + +// Test that checks template parameter support for 'sycl_esimd_vectorize' attribute on sycl device. + +// Test wrong function template instantiation and ensure that the type +// is checked properly when instantiating from the template definition. +template +// expected-error@+3{{integral constant expression must have integral or unscoped enumeration type, not 'S'}} +// expected-error@+2{{integral constant expression must have integral or unscoped enumeration type, not 'float'}} +// expected-error@+1{{'sycl_esimd_vectorize' attribute argument must be 8, 16, or 32}} +[[intel::sycl_esimd_vectorize(Ty{})]] void func() {} + +struct S {}; +void test() { + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); +} + +// Test a non-constant expression. +// expected-note@+1{{declared here}} +int foo(); +// expected-error@+2{{expression is not an integral constant expression}} +// expected-note@+1{{non-constexpr function 'foo' cannot be used in a constant expression}} +[[intel::sycl_esimd_vectorize(foo() + 12)]] void func1(); + +// Test a constant expression. +constexpr int bar() { return 0; } +[[intel::sycl_esimd_vectorize(bar() + 16)]] void func2(); // OK + +// Test template parameter support on member function of class template. +template +class KernelFunctor { +public: + // expected-error@+1{{'sycl_esimd_vectorize' attribute argument must be 8, 16, or 32}} + [[intel::sycl_esimd_vectorize(SIZE)]] void operator()() {} +}; + +int main() { + //expected-note@+1{{in instantiation of template class 'KernelFunctor<-1>' requested here}} + KernelFunctor<-1>(); + // no error expected + KernelFunctor<8>(); + return 0; +} + +// CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor +// CHECK: ClassTemplateSpecializationDecl {{.*}} {{.*}} class KernelFunctor definition +// CHECK: CXXRecordDecl {{.*}} {{.*}} implicit class KernelFunctor +// CHECK: SYCLIntelESimdVectorizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + +// Test template parameter support on function. +template +// expected-error@+1{{'sycl_esimd_vectorize' attribute argument must be 8, 16, or 32}} +[[intel::sycl_esimd_vectorize(N)]] void func3() {} + +template +[[intel::sycl_esimd_vectorize(32)]] void func4(); // expected-note {{previous attribute is here}} + +template +[[intel::sycl_esimd_vectorize(N)]] void func4() {} // expected-warning {{attribute 'sycl_esimd_vectorize' is already applied with different arguments}} + +int check() { + // no error expected. + func3<8>(); + //expected-note@+1{{in instantiation of function template specialization 'func3<-1>' requested here}} + func3<-1>(); + //expected-note@+1 {{in instantiation of function template specialization 'func4<16>' requested here}} + func4<16>(); + return 0; +} + +// No diagnostic is emitted because the arguments match. Duplicate attribute is silently ignored. +[[intel::sycl_esimd_vectorize(8)]] +[[intel::sycl_esimd_vectorize(8)]] void func5() {} + +// CHECK: FunctionTemplateDecl {{.*}} {{.*}} func3 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 0 N +// CHECK: FunctionDecl {{.*}} {{.*}} func3 'void ()' +// CHECK: SYCLIntelESimdVectorizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + +// CHECK: FunctionDecl {{.*}} {{.*}} func5 'void ()' +// CHECK: SYCLIntelESimdVectorizeAttr {{.*}} +// CHECK-NEXT: ConstantExpr {{.*}} 'int' +// CHECK-NEXT: value: Int 8 +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} From 44cc12170c591de67f40a0b2b19f54f0962d22fd Mon Sep 17 00:00:00 2001 From: Denis Bakhvalov Date: Thu, 29 Apr 2021 10:06:46 -0700 Subject: [PATCH 5/6] when merging, use the attribute from the declaration --- clang/lib/Sema/SemaDeclAttr.cpp | 7 +++++-- clang/test/CodeGenSYCL/esimd-vectorize-md.cpp | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 548fa364d08d9..d0acb0a5cc46b 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5137,9 +5137,12 @@ Sema::MergeSYCLIntelESimdVectorizeAttr(Decl *D, if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; Diag(A.getLoc(), diag::note_previous_attribute); + // Drop the attribute from the current declaration + D->dropAttr(); + } else { + // Do not add a duplicate attribute. + return nullptr; } - // Do not add a duplicate attribute. - return nullptr; } } } diff --git a/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp b/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp index 1446e4e94122d..cb5a75e1a24b6 100644 --- a/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp +++ b/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp @@ -11,8 +11,7 @@ [[intel::sycl_esimd_vectorize(8)]] __attribute__((sycl_device)) void foo3(); [[intel::sycl_esimd_vectorize(16)]] __attribute__((sycl_device)) void foo3() {} -// CHECK: @_Z4foo3v() #[[ATTR3:[0-9]+]] +// CHECK: @_Z4foo3v() #[[ATTR2]] // CHECK: attributes #[[ATTR1]] = { {{.*}} "CMGenxSIMT"="32" {{.*}}} // CHECK: attributes #[[ATTR2]] = { {{.*}} "CMGenxSIMT"="8" {{.*}}} -// CHECK: attributes #[[ATTR3]] = { {{.*}} "CMGenxSIMT"="16" {{.*}}} From 708a011a02cd1e54b71a9bf856876a8ab5aaedbb Mon Sep 17 00:00:00 2001 From: Denis Bakhvalov Date: Thu, 29 Apr 2021 13:25:56 -0700 Subject: [PATCH 6/6] Revert "when merging, use the attribute from the declaration" This reverts commit 44cc12170c591de67f40a0b2b19f54f0962d22fd. --- clang/lib/Sema/SemaDeclAttr.cpp | 7 ++----- clang/test/CodeGenSYCL/esimd-vectorize-md.cpp | 3 ++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d0acb0a5cc46b..548fa364d08d9 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5137,12 +5137,9 @@ Sema::MergeSYCLIntelESimdVectorizeAttr(Decl *D, if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; Diag(A.getLoc(), diag::note_previous_attribute); - // Drop the attribute from the current declaration - D->dropAttr(); - } else { - // Do not add a duplicate attribute. - return nullptr; } + // Do not add a duplicate attribute. + return nullptr; } } } diff --git a/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp b/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp index cb5a75e1a24b6..1446e4e94122d 100644 --- a/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp +++ b/clang/test/CodeGenSYCL/esimd-vectorize-md.cpp @@ -11,7 +11,8 @@ [[intel::sycl_esimd_vectorize(8)]] __attribute__((sycl_device)) void foo3(); [[intel::sycl_esimd_vectorize(16)]] __attribute__((sycl_device)) void foo3() {} -// CHECK: @_Z4foo3v() #[[ATTR2]] +// CHECK: @_Z4foo3v() #[[ATTR3:[0-9]+]] // CHECK: attributes #[[ATTR1]] = { {{.*}} "CMGenxSIMT"="32" {{.*}}} // CHECK: attributes #[[ATTR2]] = { {{.*}} "CMGenxSIMT"="8" {{.*}}} +// CHECK: attributes #[[ATTR3]] = { {{.*}} "CMGenxSIMT"="16" {{.*}}}