From 4d6d0b2f92fbe845e7c3b14297b3fcce596583fa Mon Sep 17 00:00:00 2001 From: Alexey Sachkov Date: Sat, 21 Dec 2019 00:52:58 +0300 Subject: [PATCH 1/9] Update usage rules of SYCL_EXTERNAL This patch allows to apply `SYCL_EXTERNAL` to class member functions, but only if they weren't declared as virtual or as pure virtual. The same logic was applied to `[[intel::device_indireclty_callable]]`. Signed-off-by: Alexey Sachkov --- clang/include/clang/Basic/AttrDocs.td | 2 +- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/AST/ASTContext.cpp | 6 ++++++ clang/lib/Sema/SemaDeclAttr.cpp | 8 ++++---- clang/test/CodeGenSYCL/sycl-device.cpp | 9 +++++++++ .../SemaSYCL/device-indirectly-callable-attr.cpp | 12 ++++++++++-- clang/test/SemaSYCL/sycl-device.cpp | 12 ++++++++++-- 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 910c6b2bee61b..aa2d772d7d7a4 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2098,7 +2098,7 @@ This attribute can only be applied to functions and indicates that the function must be treated as a device function and must be emitted even if it has no direct uses from other SYCL device functions. However, it cannot be applied to functions marked as 'static', functions declared within an anonymous -namespace or class member functions. +namespace or virtual/pure virtual class member functions. It also means that function should be available externally and cannot be optimized out due to reachability analysis or by any other diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 549907a409196..55d8bbe1d2971 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10695,7 +10695,7 @@ def warn_boolean_attribute_argument_is_not_valid: Warning< def err_sycl_attibute_cannot_be_applied_here : Error<"%0 attribute cannot be applied to a " "%select{static function or function in an anonymous namespace" - "|class member function}1">; + "|virtual or pure virtual class member function}1">; def warn_sycl_attibute_function_raw_ptr : Warning<"SYCL 1.2.1 specification does not allow %0 attribute applied " "to a function with a raw pointer " diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index b926758b01781..d05dc11574385 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -10178,6 +10178,12 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { } } + // Methods explcitly marked with 'sycl_device' attribute (via SYCL_EXTERNAL) + // must be emitted regardless of number of actual uses + if (LangOpts.SYCLIsDevice && isa(D)) + if (auto *A = D->getAttr()) + return !A->isImplicit(); + GVALinkage Linkage = GetGVALinkageForFunction(FD); // static, static inline, always_inline, and extern inline functions can diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f71b8327224aa..4ca88841590ef 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4432,9 +4432,9 @@ static void handleSYCLDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << AL << 0 /* static function or anonymous namespace */; return; } - if (isa(FD)) { + if (FD->isVirtualAsWritten() || FD->isPure()) { S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) - << AL << 1 /* class member function */; + << AL << 1 /* virtual or pure virtual class member function */; return; } if (FD->getReturnType()->isPointerType()) { @@ -4459,9 +4459,9 @@ static void handleSYCLDeviceIndirectlyCallableAttr(Sema &S, Decl *D, << AL << 0 /* static function or anonymous namespace */; return; } - if (isa(FD)) { + if (FD->isVirtualAsWritten() || FD->isPure()) { S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) - << AL << 1 /* class member function */; + << AL << 1 /* virtual or pure virtual class member function */; return; } diff --git a/clang/test/CodeGenSYCL/sycl-device.cpp b/clang/test/CodeGenSYCL/sycl-device.cpp index fb4b782f2daf7..fe2359dfb84f1 100644 --- a/clang/test/CodeGenSYCL/sycl-device.cpp +++ b/clang/test/CodeGenSYCL/sycl-device.cpp @@ -3,6 +3,15 @@ int bar(int b); +class A { +public: + // TODO: check for constructor/destructor as well + + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1A3fooEv + __attribute__((sycl_device)) + void foo() {} +}; + // CHECK-DAG: define spir_func i32 @_Z3fooii __attribute__((sycl_device)) int foo(int a, int b) { return a + bar(b); } diff --git a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp index c79e3b0317ff2..a89973b055ccb 100644 --- a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp +++ b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp @@ -19,13 +19,21 @@ namespace { } class A { - [[intel::device_indirectly_callable]] // expected-error {{'device_indirectly_callable' attribute cannot be applied to a class member function}} + [[intel::device_indirectly_callable]] A() {} - [[intel::device_indirectly_callable]] // expected-error {{'device_indirectly_callable' attribute cannot be applied to a class member function}} + [[intel::device_indirectly_callable]] int func3() {} }; +class B { + [[intel::device_indirectly_callable]] // expected-error {{'device_indirectly_callable' attribute cannot be applied to a virtual or pure virtual class member function}} + virtual int foo() {} + + [[intel::device_indirectly_callable]] // expected-error {{'device_indirectly_callable' attribute cannot be applied to a virtual or pure virtual class member function}} + virtual int bar() = 0; +}; + void helper() {} [[intel::device_indirectly_callable]] diff --git a/clang/test/SemaSYCL/sycl-device.cpp b/clang/test/SemaSYCL/sycl-device.cpp index cd56ca33b2f82..6a4d3886566e0 100644 --- a/clang/test/SemaSYCL/sycl-device.cpp +++ b/clang/test/SemaSYCL/sycl-device.cpp @@ -21,13 +21,21 @@ namespace { } class A { - __attribute__((sycl_device)) // expected-error {{'sycl_device' attribute cannot be applied to a class member function}} + __attribute__((sycl_device)) A() {} - __attribute__((sycl_device)) // expected-error {{'sycl_device' attribute cannot be applied to a class member function}} + __attribute__((sycl_device)) int func3() {} }; +class B { + __attribute__((sycl_device)) // expected-error {{'sycl_device' attribute cannot be applied to a virtual or pure virtual class member function}} + virtual int foo() {} + + __attribute__((sycl_device)) // expected-error {{'sycl_device' attribute cannot be applied to a virtual or pure virtual class member function}} + virtual int bar() = 0; +}; + #if defined(NOT_STRICT) __attribute__((sycl_device)) int* func3() { return nullptr; } From 9fdd4a1d8cf2095653294c77e7f1341b96fe0bc4 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Thu, 12 Mar 2020 15:08:22 +0300 Subject: [PATCH 2/9] Extend the test Signed-off-by: Mariya Podchishchaeva --- clang/test/CodeGenSYCL/sycl-device.cpp | 34 +++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/clang/test/CodeGenSYCL/sycl-device.cpp b/clang/test/CodeGenSYCL/sycl-device.cpp index fe2359dfb84f1..1fa28a494dd92 100644 --- a/clang/test/CodeGenSYCL/sycl-device.cpp +++ b/clang/test/CodeGenSYCL/sycl-device.cpp @@ -5,11 +5,39 @@ int bar(int b); class A { public: - // TODO: check for constructor/destructor as well - // CHECK-DAG: define linkonce_odr spir_func void @_ZN1A3fooEv + __attribute__((sycl_device)) void foo() {} + + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AC1Ev __attribute__((sycl_device)) - void foo() {} + A() {} + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AD1Ev + __attribute__((sycl_device)) ~A() {} + + template + __attribute__((sycl_device)) void AFoo(T t) {} + + // Templates are emitted when they are instantiated + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1A4AFooIiEEvT_ + template <> + __attribute__((sycl_device)) void AFoo(int t) {} +}; + +template +struct B { + T data; + B(T _data) : data(_data) {} + + __attribute__((sycl_device)) void BFoo(T t) {} +}; + +template <> +struct B { + int data; + B(int _data) : data(_data) {} + + // CHECK-DAG: _ZN1BIiE4BFooEi + __attribute__((sycl_device)) void BFoo(int t) {} }; // CHECK-DAG: define spir_func i32 @_Z3fooii From f762faac0d2a3c93672eb5df907b02c57e78fc12 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Mon, 16 Mar 2020 07:56:36 +0300 Subject: [PATCH 3/9] [SYCL] Erase diagnosing for virtual functions Signed-off-by: Mariya Podchishchaeva --- clang/include/clang/Basic/AttrDocs.td | 4 ++-- clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +-- clang/lib/Sema/SemaDeclAttr.cpp | 16 ++-------------- .../SemaSYCL/device-indirectly-callable-attr.cpp | 4 ++-- clang/test/SemaSYCL/sycl-device.cpp | 10 ++++------ 5 files changed, 11 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index aa2d772d7d7a4..0318e8480993e 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2097,8 +2097,8 @@ def SYCLDeviceIndirectlyCallableDocs : Documentation { This attribute can only be applied to functions and indicates that the function must be treated as a device function and must be emitted even if it has no direct uses from other SYCL device functions. However, it cannot be applied -to functions marked as 'static', functions declared within an anonymous -namespace or virtual/pure virtual class member functions. +to functions marked as 'static' and functions declared within an anonymous +namespace. It also means that function should be available externally and cannot be optimized out due to reachability analysis or by any other diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 55d8bbe1d2971..ee28f08d27871 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10694,8 +10694,7 @@ def warn_boolean_attribute_argument_is_not_valid: Warning< InGroup; def err_sycl_attibute_cannot_be_applied_here : Error<"%0 attribute cannot be applied to a " - "%select{static function or function in an anonymous namespace" - "|virtual or pure virtual class member function}1">; + "static function or function in an anonymous namespace">; def warn_sycl_attibute_function_raw_ptr : Warning<"SYCL 1.2.1 specification does not allow %0 attribute applied " "to a function with a raw pointer " diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 4ca88841590ef..08b59b91e2f9d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4428,13 +4428,7 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleSYCLDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { auto *FD = cast(D); if (!FD->isExternallyVisible()) { - S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) - << AL << 0 /* static function or anonymous namespace */; - return; - } - if (FD->isVirtualAsWritten() || FD->isPure()) { - S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) - << AL << 1 /* virtual or pure virtual class member function */; + S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) << AL; return; } if (FD->getReturnType()->isPointerType()) { @@ -4455,13 +4449,7 @@ static void handleSYCLDeviceIndirectlyCallableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { auto *FD = cast(D); if (!FD->isExternallyVisible()) { - S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) - << AL << 0 /* static function or anonymous namespace */; - return; - } - if (FD->isVirtualAsWritten() || FD->isPure()) { - S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) - << AL << 1 /* virtual or pure virtual class member function */; + S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) << AL; return; } diff --git a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp index a89973b055ccb..50fec383a6142 100644 --- a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp +++ b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp @@ -27,10 +27,10 @@ class A { }; class B { - [[intel::device_indirectly_callable]] // expected-error {{'device_indirectly_callable' attribute cannot be applied to a virtual or pure virtual class member function}} + [[intel::device_indirectly_callable]] virtual int foo() {} - [[intel::device_indirectly_callable]] // expected-error {{'device_indirectly_callable' attribute cannot be applied to a virtual or pure virtual class member function}} + [[intel::device_indirectly_callable]] virtual int bar() = 0; }; diff --git a/clang/test/SemaSYCL/sycl-device.cpp b/clang/test/SemaSYCL/sycl-device.cpp index 6a4d3886566e0..131b038b220a6 100644 --- a/clang/test/SemaSYCL/sycl-device.cpp +++ b/clang/test/SemaSYCL/sycl-device.cpp @@ -24,16 +24,14 @@ class A { __attribute__((sycl_device)) A() {} - __attribute__((sycl_device)) - int func3() {} + __attribute__((sycl_device)) void func3() {} }; class B { - __attribute__((sycl_device)) // expected-error {{'sycl_device' attribute cannot be applied to a virtual or pure virtual class member function}} - virtual int foo() {} +public: + __attribute__((sycl_device)) virtual void foo() {} - __attribute__((sycl_device)) // expected-error {{'sycl_device' attribute cannot be applied to a virtual or pure virtual class member function}} - virtual int bar() = 0; + __attribute__((sycl_device)) virtual void bar() = 0; }; #if defined(NOT_STRICT) From cd1b06cb88d643dceb26c77f0892b8f5c8b8e775 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Mon, 16 Mar 2020 08:11:13 +0300 Subject: [PATCH 4/9] Apply clang format to the test Signed-off-by: Mariya Podchishchaeva --- .../SemaSYCL/device-indirectly-callable-attr.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp index 50fec383a6142..f3626f04bf801 100644 --- a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp +++ b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp @@ -19,19 +19,15 @@ namespace { } class A { - [[intel::device_indirectly_callable]] - A() {} + [[intel::device_indirectly_callable]] A() {} - [[intel::device_indirectly_callable]] - int func3() {} + [[intel::device_indirectly_callable]] int func3() {} }; class B { - [[intel::device_indirectly_callable]] - virtual int foo() {} + [[intel::device_indirectly_callable]] virtual int foo(){} - [[intel::device_indirectly_callable]] - virtual int bar() = 0; + [[intel::device_indirectly_callable]] virtual int bar() = 0; }; void helper() {} From 2aef15774c07192a0933186ce58d2e3bddcf303d Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Mon, 16 Mar 2020 08:15:35 +0300 Subject: [PATCH 5/9] More clang format Signed-off-by: Mariya Podchishchaeva --- clang/test/SemaSYCL/device-indirectly-callable-attr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp index f3626f04bf801..a29d6b48e013d 100644 --- a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp +++ b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp @@ -25,7 +25,7 @@ class A { }; class B { - [[intel::device_indirectly_callable]] virtual int foo(){} + [[intel::device_indirectly_callable]] virtual int foo() {} [[intel::device_indirectly_callable]] virtual int bar() = 0; }; From 2225ffd276626dae43ff7ac3a94e1a7bc6fc6040 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Tue, 17 Mar 2020 18:22:45 +0300 Subject: [PATCH 6/9] [SYCL] Move device code outlining to CodeGen, add tests Moved device code outlining to CodeGen because the old scheme in combination with SYCL_EXTERNAL implementation for methods triggered assertions Signed-off-by: Mariya Podchishchaeva --- clang/lib/AST/ASTContext.cpp | 12 +++- clang/lib/CodeGen/CodeGenModule.cpp | 10 +-- clang/lib/Sema/SemaDeclAttr.cpp | 2 - clang/lib/Sema/SemaSYCL.cpp | 53 +--------------- .../device-indirectly-callable-attr.cpp | 63 +++++++++++++++++-- clang/test/CodeGenSYCL/sycl-device.cpp | 42 ++++++++++++- .../SemaSYCL/call-to-undefined-function.cpp | 3 + .../device-indirectly-callable-attr.cpp | 1 - 8 files changed, 117 insertions(+), 69 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d05dc11574385..e3b830ed4e452 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -10156,6 +10156,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (D->hasAttr() || D->hasAttr()) return true; + if (LangOpts.SYCLIsDevice && !D->hasAttr() && + !D->hasAttr()) + return false; + if (const auto *FD = dyn_cast(D)) { // Forward declarations aren't required. if (!FD->doesThisDeclarationHaveABody()) @@ -10179,10 +10183,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { } // Methods explcitly marked with 'sycl_device' attribute (via SYCL_EXTERNAL) - // must be emitted regardless of number of actual uses - if (LangOpts.SYCLIsDevice && isa(D)) + // or `indirectly_callable' attribute must be emitted regardless of number + // of actual uses + if (LangOpts.SYCLIsDevice && isa(D)) { + if (auto *A = D->getAttr()) + return !A->isImplicit(); if (auto *A = D->getAttr()) return !A->isImplicit(); + } GVALinkage Linkage = GetGVALinkageForFunction(FD); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index f926e2bf6d0f7..de7a5215c0562 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2516,11 +2516,6 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { if (Global->hasAttr()) return emitIFuncDefinition(GD); - if (LangOpts.SYCLIsDevice) { - if (!Global->hasAttr()) - return; - } - // If this is a cpu_dispatch multiversion function, emit the resolver. if (Global->hasAttr()) return emitCPUDispatchDefinition(GD); @@ -2565,6 +2560,11 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { } } + if (LangOpts.SYCLIsDevice && MustBeEmitted(Global)) { + addDeferredDeclToEmit(GD); + return; + } + // Ignore declarations, they will be emitted on their first use. if (const auto *FD = dyn_cast(Global)) { // Forward declarations are emitted lazily on first use. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 08b59b91e2f9d..26031773d46e3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4441,7 +4441,6 @@ static void handleSYCLDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << AL << 1 /* function with a raw pointer parameter type */; } - S.addSyclDeviceDecl(D); handleSimpleAttribute(S, D, AL); } @@ -4453,7 +4452,6 @@ static void handleSYCLDeviceIndirectlyCallableAttr(Sema &S, Decl *D, return; } - S.addSyclDeviceDecl(D); D->addAttr(SYCLDeviceAttr::CreateImplicit(S.Context)); handleSimpleAttribute(S, D, AL); } diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index b31bc2ec7cdde..0b3a0754951f7 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -228,12 +228,6 @@ class MarkDeviceFunction : public RecursiveASTVisitor { CheckSYCLType(Callee->getReturnType(), Callee->getSourceRange()); - if (FunctionDecl *Def = Callee->getDefinition()) { - if (!Def->hasAttr()) { - Def->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context)); - SemaRef.addSyclDeviceDecl(Def); - } - } if (auto const *FD = dyn_cast(Callee)) { // FIXME: We need check all target specified attributes for error if // that function with attribute can not be called from sycl kernel. The @@ -265,23 +259,6 @@ class MarkDeviceFunction : public RecursiveASTVisitor { bool VisitCXXConstructExpr(CXXConstructExpr *E) { for (const auto &Arg : E->arguments()) CheckSYCLType(Arg->getType(), Arg->getSourceRange()); - - CXXConstructorDecl *Ctor = E->getConstructor(); - - if (FunctionDecl *Def = Ctor->getDefinition()) { - Def->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context)); - SemaRef.addSyclDeviceDecl(Def); - } - - const auto *ConstructedType = Ctor->getParent(); - if (ConstructedType->hasUserDeclaredDestructor()) { - CXXDestructorDecl *Dtor = ConstructedType->getDestructor(); - - if (FunctionDecl *Def = Dtor->getDefinition()) { - Def->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context)); - SemaRef.addSyclDeviceDecl(Def); - } - } return true; } @@ -330,25 +307,6 @@ class MarkDeviceFunction : public RecursiveASTVisitor { return true; } - bool VisitCXXNewExpr(CXXNewExpr *E) { - // Memory storage allocation is not allowed in kernels. - // All memory allocation for the device is done on - // the host using accessor classes. Consequently, the default - // allocation operator new overloads that allocate - // storage are disallowed in a SYCL kernel. The placement - // new operator and any user-defined overloads that - // do not allocate storage are permitted. - if (FunctionDecl *FD = E->getOperatorNew()) { - if (FunctionDecl *Def = FD->getDefinition()) { - if (!Def->hasAttr()) { - Def->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context)); - SemaRef.addSyclDeviceDecl(Def); - } - } - } - return true; - } - // The call graph for this translation unit. CallGraph SYCLCG; // The set of functions called by a kernel function. @@ -1389,13 +1347,8 @@ void Sema::MarkDevice(void) { } } for (const auto &elt : Marker.KernelSet) { - if (FunctionDecl *Def = elt->getDefinition()) { - if (!Def->hasAttr()) { - Def->addAttr(SYCLDeviceAttr::CreateImplicit(Context)); - addSyclDeviceDecl(Def); - } + if (FunctionDecl *Def = elt->getDefinition()) Marker.TraverseStmt(Def->getBody()); - } } } @@ -1467,10 +1420,6 @@ static void emitCallToUndefinedFnDiag(Sema &SemaRef, const FunctionDecl *Callee, if (Callee->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) return; - // Don't emit diagnostic for functions not called from device code - if (!Caller->hasAttr() && !Caller->hasAttr()) - return; - bool RedeclHasAttr = false; for (const Decl *Redecl : Callee->redecls()) { diff --git a/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp b/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp index fe24b6103c3cb..e5eb93077049c 100644 --- a/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp +++ b/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp @@ -7,10 +7,65 @@ void foo() { helper(); } -// CHECK: define spir_func void @{{.*foo.*}}() #[[ATTRS_FOO:[0-9]+]] +// CHECK: define spir_func void @{{.*foo.*}}() #[[ATTRS_INDIR_CALL:[0-9]+]] // CHECK: call spir_func void @{{.*helper.*}}() // -// CHECK: define spir_func void @{{.*helper.*}}() #[[ATTRS_HELPER:[0-9]+]] +// CHECK: define spir_func void @{{.*helper.*}}() #[[ATTRS_NOT_INDIR_CALL:[0-9]+]] // -// CHECK: attributes #[[ATTRS_FOO]] = { {{.*}} "referenced-indirectly" -// CHECK-NOT: attributes #[[ATTRS_HELPER]] = { {{.*}} "referenced-indirectly" + +int bar20(int a) { return a + 20; } + +class A { +public: + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1A3fooEv{{.*}}#[[ATTRS_INDIR_CALL]] + // CHECK-DAG: define spir_func i32 @_Z5bar20{{.*}}#[[ATTRS_NOT_INDIR_CALL]] + [[intel::device_indirectly_callable]] void foo() { bar20(10); } + + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AC1Ev{{.*}}#[[ATTRS_INDIR_CALL]] + [[intel::device_indirectly_callable]] A() {} + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AD1Ev{{.*}}#[[ATTRS_INDIR_CALL]] + [[intel::device_indirectly_callable]] ~A() {} + + template + [[intel::device_indirectly_callable]] void AFoo(T t) {} + + // Templates are emitted when they are instantiated + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1A4AFooIiEEvT_{{.*}}#[[ATTRS_INDIR_CALL]] + template <> + [[intel::device_indirectly_callable]] void AFoo(int t) {} +}; + + +struct Base { + // CHECK-DAG: define linkonce_odr spir_func void @_ZN4Base12BaseWithAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] + [[intel::device_indirectly_callable]] virtual void BaseWithAttr() { int a = 10; } + virtual void BaseWithoutAttr() {int b = 20; } +}; + +struct Overrider : Base { + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Overrider12BaseWithAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] + [[intel::device_indirectly_callable]] void BaseWithAttr() override { int a = 20; } + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Overrider15BaseWithoutAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] + [[intel::device_indirectly_callable]] void BaseWithoutAttr() override { int b = 30; } +}; + +struct Overrider1 : Base { + // CHECK-NOT: define linkonce_odr spir_func void @_ZN10Overrider112BaseWithAttrEv + void BaseWithAttr() override { int a = 20; } +}; + + +struct Finalizer : Base { + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Finalizer12BaseWithAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] + [[intel::device_indirectly_callable]] void BaseWithAttr() final { int a = 20; } + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Finalizer15BaseWithoutAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] + [[intel::device_indirectly_callable]] void BaseWithoutAttr() final { int b = 30; } +}; + +struct Finalizer1 : Base { + // CHECK-NOT: define linkonce_odr spir_func void @_ZN10Finalizer112BaseWithAttrEv + void BaseWithAttr() final { int a = 20; } +}; + +// CHECK: attributes #[[ATTRS_INDIR_CALL]] = { {{.*}} "referenced-indirectly" +// CHECK-NOT: attributes #[[ATTRS_NOT_INDIR_CALL]] = { {{.*}} "referenced-indirectly" diff --git a/clang/test/CodeGenSYCL/sycl-device.cpp b/clang/test/CodeGenSYCL/sycl-device.cpp index 1fa28a494dd92..89874571de767 100644 --- a/clang/test/CodeGenSYCL/sycl-device.cpp +++ b/clang/test/CodeGenSYCL/sycl-device.cpp @@ -3,14 +3,19 @@ int bar(int b); +int bar10(int a) { return a + 10; } +int bar20(int a) { return a + 20; } + class A { public: // CHECK-DAG: define linkonce_odr spir_func void @_ZN1A3fooEv - __attribute__((sycl_device)) void foo() {} + // CHECK-DAG: define spir_func i32 @_Z5bar20i + __attribute__((sycl_device)) void foo() { bar20(10); } // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AC1Ev __attribute__((sycl_device)) - A() {} + A() { bar10(10); } + // CHECK-DAG: define spir_func i32 @_Z5bar10i // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AD1Ev __attribute__((sycl_device)) ~A() {} @@ -36,10 +41,41 @@ struct B { int data; B(int _data) : data(_data) {} - // CHECK-DAG: _ZN1BIiE4BFooEi + // CHECK-DAG: define linkonce_odr spir_func void @_ZN1BIiE4BFooEi __attribute__((sycl_device)) void BFoo(int t) {} }; +struct Base { + // CHECK-DAG: define linkonce_odr spir_func void @_ZN4Base12BaseWithAttrEv + __attribute__((sycl_device)) virtual void BaseWithAttr() { int a = 10; } + virtual void BaseWithoutAttr() {int b = 20; } +}; + +struct Overrider : Base { + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Overrider12BaseWithAttrEv + __attribute__((sycl_device)) void BaseWithAttr() override { int a = 20; } + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Overrider15BaseWithoutAttrEv + __attribute__((sycl_device)) void BaseWithoutAttr() override { int b = 30; } +}; + +struct Overrider1 : Base { + // CHECK-NOT: define linkonce_odr spir_func void @_ZN10Overrider112BaseWithAttrEv + void BaseWithAttr() override { int a = 20; } +}; + + +struct Finalizer : Base { + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Finalizer12BaseWithAttrEv + __attribute__((sycl_device)) void BaseWithAttr() final { int a = 20; } + // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Finalizer15BaseWithoutAttrEv + __attribute__((sycl_device)) void BaseWithoutAttr() final { int b = 30; } +}; + +struct Finalizer1 : Base { + // CHECK-NOT: define linkonce_odr spir_func void @_ZN10Finalizer112BaseWithAttrEv + void BaseWithAttr() final { int a = 20; } +}; + // CHECK-DAG: define spir_func i32 @_Z3fooii __attribute__((sycl_device)) int foo(int a, int b) { return a + bar(b); } diff --git a/clang/test/SemaSYCL/call-to-undefined-function.cpp b/clang/test/SemaSYCL/call-to-undefined-function.cpp index 6dc8d1f8a70a7..cc30af261936e 100644 --- a/clang/test/SemaSYCL/call-to-undefined-function.cpp +++ b/clang/test/SemaSYCL/call-to-undefined-function.cpp @@ -92,6 +92,9 @@ void forwardDeclFn() { } int main() { + // No problems in host code + undefined(); + kernel_single_task([]() { // expected-note@-1 {{called by 'operator()'}} // expected-note@-2 {{called by 'operator()'}} diff --git a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp index a29d6b48e013d..7d8ff0e817983 100644 --- a/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp +++ b/clang/test/SemaSYCL/device-indirectly-callable-attr.cpp @@ -45,7 +45,6 @@ void baz() {} #endif // NO_SYCL // CHECK: FunctionDecl {{.*}} helper -// CHECK: SYCLDeviceAttr // // CHECK: FunctionDecl {{.*}} foo // CHECK: SYCLDeviceAttr From 28ca593b398ad60b7af9c850e25ce6b57120b090 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Wed, 18 Mar 2020 08:08:05 +0300 Subject: [PATCH 7/9] Do not add sycl_device to global vars too Signed-off-by: Mariya Podchishchaeva --- clang/lib/Sema/SemaSYCL.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 0b3a0754951f7..0f24af372bcf7 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -298,12 +298,6 @@ class MarkDeviceFunction : public RecursiveASTVisitor { return true; CheckSYCLType(E->getType(), E->getSourceRange()); - if (VarDecl *VD = dyn_cast(D)) { - if (!VD->isLocalVarDeclOrParm() && VD->hasGlobalStorage()) { - VD->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context)); - SemaRef.addSyclDeviceDecl(VD); - } - } return true; } From a0507316a4341b17c0db94acc75e8bf352eb1342 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Wed, 18 Mar 2020 08:09:04 +0300 Subject: [PATCH 8/9] Apply clang-format to the tests Signed-off-by: Mariya Podchishchaeva --- .../device-indirectly-callable-attr.cpp | 14 ++++++-------- clang/test/CodeGenSYCL/sycl-device.cpp | 3 +-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp b/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp index e5eb93077049c..0a7e0cd602893 100644 --- a/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp +++ b/clang/test/CodeGenSYCL/device-indirectly-callable-attr.cpp @@ -35,18 +35,17 @@ class A { [[intel::device_indirectly_callable]] void AFoo(int t) {} }; - struct Base { // CHECK-DAG: define linkonce_odr spir_func void @_ZN4Base12BaseWithAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] - [[intel::device_indirectly_callable]] virtual void BaseWithAttr() { int a = 10; } - virtual void BaseWithoutAttr() {int b = 20; } + [[intel::device_indirectly_callable]] virtual void BaseWithAttr() { int a = 10; } + virtual void BaseWithoutAttr() { int b = 20; } }; struct Overrider : Base { // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Overrider12BaseWithAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] - [[intel::device_indirectly_callable]] void BaseWithAttr() override { int a = 20; } + [[intel::device_indirectly_callable]] void BaseWithAttr() override { int a = 20; } // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Overrider15BaseWithoutAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] - [[intel::device_indirectly_callable]] void BaseWithoutAttr() override { int b = 30; } + [[intel::device_indirectly_callable]] void BaseWithoutAttr() override { int b = 30; } }; struct Overrider1 : Base { @@ -54,12 +53,11 @@ struct Overrider1 : Base { void BaseWithAttr() override { int a = 20; } }; - struct Finalizer : Base { // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Finalizer12BaseWithAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] - [[intel::device_indirectly_callable]] void BaseWithAttr() final { int a = 20; } + [[intel::device_indirectly_callable]] void BaseWithAttr() final { int a = 20; } // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Finalizer15BaseWithoutAttrEv{{.*}}#[[ATTRS_INDIR_CALL]] - [[intel::device_indirectly_callable]] void BaseWithoutAttr() final { int b = 30; } + [[intel::device_indirectly_callable]] void BaseWithoutAttr() final { int b = 30; } }; struct Finalizer1 : Base { diff --git a/clang/test/CodeGenSYCL/sycl-device.cpp b/clang/test/CodeGenSYCL/sycl-device.cpp index 89874571de767..8109edbfda579 100644 --- a/clang/test/CodeGenSYCL/sycl-device.cpp +++ b/clang/test/CodeGenSYCL/sycl-device.cpp @@ -48,7 +48,7 @@ struct B { struct Base { // CHECK-DAG: define linkonce_odr spir_func void @_ZN4Base12BaseWithAttrEv __attribute__((sycl_device)) virtual void BaseWithAttr() { int a = 10; } - virtual void BaseWithoutAttr() {int b = 20; } + virtual void BaseWithoutAttr() { int b = 20; } }; struct Overrider : Base { @@ -63,7 +63,6 @@ struct Overrider1 : Base { void BaseWithAttr() override { int a = 20; } }; - struct Finalizer : Base { // CHECK-DAG: define linkonce_odr spir_func void @_ZN9Finalizer12BaseWithAttrEv __attribute__((sycl_device)) void BaseWithAttr() final { int a = 20; } From 1c3036c5dd436377dc07ade6e2277e7242b3df96 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Wed, 18 Mar 2020 09:17:27 +0300 Subject: [PATCH 9/9] Apply comments Signed-off-by: Mariya Podchishchaeva --- clang/test/CodeGenSYCL/sycl-device.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/test/CodeGenSYCL/sycl-device.cpp b/clang/test/CodeGenSYCL/sycl-device.cpp index 8109edbfda579..49f8def476d98 100644 --- a/clang/test/CodeGenSYCL/sycl-device.cpp +++ b/clang/test/CodeGenSYCL/sycl-device.cpp @@ -13,9 +13,9 @@ class A { __attribute__((sycl_device)) void foo() { bar20(10); } // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AC1Ev + // CHECK-DAG: define spir_func i32 @_Z5bar10i __attribute__((sycl_device)) A() { bar10(10); } - // CHECK-DAG: define spir_func i32 @_Z5bar10i // CHECK-DAG: define linkonce_odr spir_func void @_ZN1AD1Ev __attribute__((sycl_device)) ~A() {} @@ -26,6 +26,12 @@ class A { // CHECK-DAG: define linkonce_odr spir_func void @_ZN1A4AFooIiEEvT_ template <> __attribute__((sycl_device)) void AFoo(int t) {} + + // CHECK-DAG: define linkonce_odr spir_func i32 @_ZN1A13non_annotatedEv + int non_annotated() { return 1; } + + // CHECK-DAG: define linkonce_odr spir_func i32 @_ZN1A9annotatedEv + __attribute__((sycl_device)) int annotated() { return non_annotated() + 1; } }; template