From d9660d060957a6b3faf88408dc89099ad9f41b75 Mon Sep 17 00:00:00 2001 From: Premanand M Rao Date: Tue, 30 Jun 2020 18:12:46 -0700 Subject: [PATCH 1/5] [SYCL] Do not emit const static data members that are not const-initialized Const static data members need to be either zero-initialized or constant-initialized. We were emitting all const static data members before, which needed address space casts from constant-space to private-space. This change also reverts the address-space cast introduced in https://github.com/intel/llvm/pull/1774 Signed-off-by: Premanand M Rao --- clang/lib/CodeGen/CodeGenModule.cpp | 3 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +- .../CodeGenSYCL/sycl-device-const-sdm.cpp | 91 +++++++++++++++++++ .../CodeGenSYCL/sycl-device-static-init.cpp | 3 +- 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index a6e440c3a8daa..2bdfb4dfd784e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1288,8 +1288,7 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { ctor.addInt(Int32Ty, I.Priority); ctor.add(llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy)); if (I.AssociatedData) - ctor.add(llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( - I.AssociatedData, VoidPtrTy)); + ctor.add(llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy)); else ctor.addNullPointer(VoidPtrTy); ctor.finishAndAddTo(ctors); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 49e82c02939b1..3154b973f3ac9 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5255,7 +5255,10 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // Do not explicitly emit non-const static data member definitions // on SYCL device. if (!SemaRef.getLangOpts().SYCLIsDevice || !Var->isStaticDataMember() || - Var->isConstexpr() || Var->getType().isConstQualified()) + Var->isConstexpr() || + (Var->getType().isConstQualified() && Var->getInit() && + Var->getInit()->isConstantInitializer(SemaRef.getASTContext(), + false))) Consumer.HandleCXXStaticMemberVarInstantiation(Var); } } PassToConsumerRAII(*this, Consumer, Var); diff --git a/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp b/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp new file mode 100644 index 0000000000000..a8b9d5cf498de --- /dev/null +++ b/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s +// Tests that static data members that are not constant-initialized are not +// emitted in device code. + +// CHECK:%struct._ZTS1B.B = type { i8 } +// CHECK:%struct._ZTS1C.C = type { i32, i32 } +// CHECK:%struct._ZTS1D.D = type { i8 } +// CHECK:$_ZN2TTIiE2c1E = comdat any +// CHECK:$_ZN2TTIiE2d1E = comdat any +// CHECK:$_ZN2TTIiE4var1E = comdat any +// CHECK:$_ZN2TTIiE4var3E = comdat any +// CHECK:@_ZN1S2b1E = addrspace(1) global %struct._ZTS1B.B zeroinitializer, align 1 +// CHECK:@_ZN1S2c1E = addrspace(1) constant %struct._ZTS1C.C { i32 2, i32 5 }, align 4 +// CHECK:@_ZN1S2d1E = addrspace(1) constant %struct._ZTS1D.D zeroinitializer, align 1 +// CHECK:@_ZN1S4var1E = addrspace(1) constant i32 1, align 4 +// CHECK:@_ZN1S4var2E = available_externally addrspace(1) constant i32 3, align 4 +// CHECK:@_ZN1S4var3E = addrspace(1) constant i32 4, align 4 +// CHECK:@_ZN2TTIiE2b1E = external addrspace(1) global %struct._ZTS1B.B, align 1 +// CHECK:@_ZN2TTIiE2c1E = linkonce_odr addrspace(1) constant %struct._ZTS1C.C { i32 2, i32 5 }, comdat, align 4 +// CHECK:@_ZN2TTIiE2d1E = linkonce_odr addrspace(1) constant %struct._ZTS1D.D zeroinitializer, comdat, align 1 +// CHECK:@_ZN2TTIiE4var1E = linkonce_odr addrspace(1) constant i32 1, comdat, align 4 +// CHECK:@_ZN2TTIiE4var2E = available_externally addrspace(1) constant i32 3, align 4 +// CHECK:@_ZN2TTIiE4var3E = linkonce_odr addrspace(1) constant i32 4, comdat, align 4 +// CHECK:@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535 +// CHECK-NOT: addrspacecast +// CHECK: define spir_kernel void @_ZTSZ4mainE11fake_kernel() + +struct TestBaseType {}; +struct B { + B(); +}; +struct C { + int i, j; +}; +struct D { +}; + +struct S { + static const B b1; + static const int var1; + static constexpr const int var2 = 3; + static const int var3; + static const C c1; + static const D d1; +}; +const B S::b1; +const C S::c1{2, 5}; +const int S::var1 = 1; +const int S::var3 = 1 + 3; +const D S::d1; + +template +struct TT { + static const B b1; + static const int var1; + static constexpr const int var2 = 3; + static const int var3; + static const C c1; + static const D d1; +}; +template +const B TT::b1; +template +const C TT::c1{2, 5}; +template +const int TT::var1 = 1; +template +const int TT::var3 = 1 + 3; +template +const D TT::d1; + +template +__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { + kernelFunc(); + (void)S::b1; + (void)S::c1; + (void)S::d1; + (void)S::var1; + (void)S::var2; + (void)S::var3; + (void)TT::b1; + (void)TT::c1; + (void)TT::d1; + (void)TT::var1; + (void)TT::var2; + (void)TT::var3; +} +int main() { + kernel_single_task([=]() {}); + return 0; +} diff --git a/clang/test/CodeGenSYCL/sycl-device-static-init.cpp b/clang/test/CodeGenSYCL/sycl-device-static-init.cpp index 8ff1869ed7d74..1f4ec1f8c1efc 100644 --- a/clang/test/CodeGenSYCL/sycl-device-static-init.cpp +++ b/clang/test/CodeGenSYCL/sycl-device-static-init.cpp @@ -4,10 +4,9 @@ // CHECK: %struct._ZTS16RegisterBaseInit.RegisterBaseInit = type { i8 } // CHECK-NOT: $_ZN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = comdat any // CHECK: $_ZN8BaseInitI12TestBaseTypeE3varE = comdat any +// CHECK: @_ZN8BaseInitI12TestBaseTypeE3varE = weak_odr addrspace(1) constant i32 9, comdat, align 4 // CHECK: @_ZN8BaseInitI12TestBaseTypeE9s_regbaseE = {{.*}} global %struct._ZTS16RegisterBaseInit.RegisterBaseInit // CHECK-NOT: @_ZN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = weak_odr addrspace(1) global %struct._ZTS16RegisterBaseInit.RegisterBaseInit zeroinitializer, comdat, align 1 -// CHECK: @_ZN8BaseInitI12TestBaseTypeE3varE = weak_odr addrspace(1) constant i32 9, comdat, align 4 -// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init, i8* addrspacecast (i8 addrspace(1)* getelementptr inbounds (%struct._ZTS16RegisterBaseInit.RegisterBaseInit, %struct._ZTS16RegisterBaseInit.RegisterBaseInit addrspace(1)* @_ZN8BaseInitI12TestBaseTypeE9s_regbaseE, i32 0, i32 0) to i8*) }] // CHECK-NOT: @_ZGVN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = weak_odr global i64 0, comdat($_ZN8BaseInitI12TestBaseTypeE9s_regbaseE), align 8 // CHECK: define spir_kernel void @_ZTSZ4mainE11fake_kernel() // CHECK: call spir_func void @"_ZZ4mainENK3$_0clE16RegisterBaseInit From fedfdd33b3c46271a3e5e3cb2fb8e7158e16b604 Mon Sep 17 00:00:00 2001 From: Premanand M Rao Date: Thu, 2 Jul 2020 19:34:18 -0700 Subject: [PATCH 2/5] [SYCL] Do not emit const sdm initializers Const static data members need to be either zero-initialized or constant-initialized. We were emitting initializers for all const static data members before, which needed invalid address space casts from constant-space to private-space. This change also reverts the address-space cast introduced in https://github.com/intel/llvm/pull/1774 Signed-off-by: Premanand M Rao --- .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/include/clang/Sema/Sema.h | 5 ++- clang/lib/Sema/SemaExpr.cpp | 7 +++++ clang/lib/Sema/SemaSYCL.cpp | 21 +++++++++++++ .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 +++ .../CodeGenSYCL/sycl-device-const-sdm.cpp | 15 +-------- .../CodeGenSYCL/sycl-device-static-init.cpp | 10 ++---- .../SemaSYCL/sycl-device-const-static.cpp | 31 +++++++++++++++++-- 8 files changed, 70 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 42456865f2567..27b593d923901 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10850,6 +10850,8 @@ def err_sycl_restrict : Error< "|call a dllimport function" "|call a variadic function" "|call an undefined function without SYCL_EXTERNAL attribute" + "|use a const static data variable that is neither zero-initialized " + "nor constant-initialized" "}0">; def err_sycl_virtual_types : Error< "No class with a vtable can be used in a SYCL kernel or any code included in the kernel">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fe00bbcf63d66..df3aa9dcb57d2 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9943,6 +9943,8 @@ class Sema final { void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *ID); bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type); + bool checkAllowedSYCLInitializer(VarDecl *VD, + bool CheckValueDependent = false); // Adds an intel_reqd_sub_group_size attribute to a particular declaration. void addIntelReqdSubGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, @@ -12659,7 +12661,8 @@ class Sema final { KernelUseAssembly, KernelCallDllimportFunction, KernelCallVariadicFunction, - KernelCallUndefinedFunction + KernelCallUndefinedFunction, + KernelConstStaticDataVariable }; bool isKnownGoodSYCLDecl(const Decl *D); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d613db8a6b100..41370c4867fa6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -223,6 +223,13 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, VD->hasGlobalStorage() && !isa(VD)) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) << Sema::KernelGlobalVariable; + // Disallow const static data members that are not zero-initialized + // or constant-initialized + else if (IsConst && VD->isStaticDataMember() && + !VD->isConstexpr() && + !checkAllowedSYCLInitializer(VD, /*checkValueDependent =*/true)) + SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) + << Sema::KernelConstStaticDataVariable; } } diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 09d5a45b306d0..9c89b82a9b951 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -1845,6 +1845,27 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller, } } +bool Sema::checkAllowedSYCLInitializer(VarDecl *VD, bool CheckValueDependent) { + assert(getLangOpts().SYCLIsDevice && + "Should only be called during SYCL compilation"); + + if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage()) + return true; + + const Expr *Init = VD->getInit(); + bool ValueDependent = CheckValueDependent && Init->isValueDependent(); + bool isZeroInit = Init && !ValueDependent && + Init->isIntegerConstantExpr(Context) && + Init->EvaluateKnownConstInt(Context) == 0; + bool isConstantInit = Init && !ValueDependent && + Init->isConstantInitializer(Context, false); + if (!VD->isConstexpr() && Init && !ValueDependent && !isZeroInit && + !isConstantInit) + return false; + + return true; +} + // ----------------------------------------------------------------------------- // Integration header functionality implementation // ----------------------------------------------------------------------------- diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3154b973f3ac9..8a8859abf8efc 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5101,6 +5101,10 @@ void Sema::InstantiateVariableInitializer( if (getLangOpts().CUDA) checkAllowedCUDAInitializer(Var); + + if (getLangOpts().SYCLIsDevice && !checkAllowedSYCLInitializer(Var)) + SYCLDiagIfDeviceCode(Var->getLocation(), diag::err_sycl_restrict) + << Sema::KernelConstStaticDataVariable; } /// Instantiate the definition of the given variable from its diff --git a/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp b/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp index a8b9d5cf498de..8ce7470064172 100644 --- a/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp +++ b/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp @@ -2,33 +2,27 @@ // Tests that static data members that are not constant-initialized are not // emitted in device code. -// CHECK:%struct._ZTS1B.B = type { i8 } // CHECK:%struct._ZTS1C.C = type { i32, i32 } // CHECK:%struct._ZTS1D.D = type { i8 } // CHECK:$_ZN2TTIiE2c1E = comdat any // CHECK:$_ZN2TTIiE2d1E = comdat any // CHECK:$_ZN2TTIiE4var1E = comdat any // CHECK:$_ZN2TTIiE4var3E = comdat any -// CHECK:@_ZN1S2b1E = addrspace(1) global %struct._ZTS1B.B zeroinitializer, align 1 // CHECK:@_ZN1S2c1E = addrspace(1) constant %struct._ZTS1C.C { i32 2, i32 5 }, align 4 // CHECK:@_ZN1S2d1E = addrspace(1) constant %struct._ZTS1D.D zeroinitializer, align 1 // CHECK:@_ZN1S4var1E = addrspace(1) constant i32 1, align 4 // CHECK:@_ZN1S4var2E = available_externally addrspace(1) constant i32 3, align 4 // CHECK:@_ZN1S4var3E = addrspace(1) constant i32 4, align 4 -// CHECK:@_ZN2TTIiE2b1E = external addrspace(1) global %struct._ZTS1B.B, align 1 // CHECK:@_ZN2TTIiE2c1E = linkonce_odr addrspace(1) constant %struct._ZTS1C.C { i32 2, i32 5 }, comdat, align 4 // CHECK:@_ZN2TTIiE2d1E = linkonce_odr addrspace(1) constant %struct._ZTS1D.D zeroinitializer, comdat, align 1 // CHECK:@_ZN2TTIiE4var1E = linkonce_odr addrspace(1) constant i32 1, comdat, align 4 // CHECK:@_ZN2TTIiE4var2E = available_externally addrspace(1) constant i32 3, align 4 // CHECK:@_ZN2TTIiE4var3E = linkonce_odr addrspace(1) constant i32 4, comdat, align 4 -// CHECK:@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535 +// CHECK-NOT:@llvm.global_ctors = // CHECK-NOT: addrspacecast // CHECK: define spir_kernel void @_ZTSZ4mainE11fake_kernel() struct TestBaseType {}; -struct B { - B(); -}; struct C { int i, j; }; @@ -36,14 +30,12 @@ struct D { }; struct S { - static const B b1; static const int var1; static constexpr const int var2 = 3; static const int var3; static const C c1; static const D d1; }; -const B S::b1; const C S::c1{2, 5}; const int S::var1 = 1; const int S::var3 = 1 + 3; @@ -51,7 +43,6 @@ const D S::d1; template struct TT { - static const B b1; static const int var1; static constexpr const int var2 = 3; static const int var3; @@ -59,8 +50,6 @@ struct TT { static const D d1; }; template -const B TT::b1; -template const C TT::c1{2, 5}; template const int TT::var1 = 1; @@ -72,13 +61,11 @@ const D TT::d1; template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { kernelFunc(); - (void)S::b1; (void)S::c1; (void)S::d1; (void)S::var1; (void)S::var2; (void)S::var3; - (void)TT::b1; (void)TT::c1; (void)TT::d1; (void)TT::var1; diff --git a/clang/test/CodeGenSYCL/sycl-device-static-init.cpp b/clang/test/CodeGenSYCL/sycl-device-static-init.cpp index 1f4ec1f8c1efc..b811b1061bfd6 100644 --- a/clang/test/CodeGenSYCL/sycl-device-static-init.cpp +++ b/clang/test/CodeGenSYCL/sycl-device-static-init.cpp @@ -1,16 +1,13 @@ // RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s // Test that static initializers do not force the emission of globals on sycl device -// CHECK: %struct._ZTS16RegisterBaseInit.RegisterBaseInit = type { i8 } // CHECK-NOT: $_ZN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = comdat any // CHECK: $_ZN8BaseInitI12TestBaseTypeE3varE = comdat any // CHECK: @_ZN8BaseInitI12TestBaseTypeE3varE = weak_odr addrspace(1) constant i32 9, comdat, align 4 -// CHECK: @_ZN8BaseInitI12TestBaseTypeE9s_regbaseE = {{.*}} global %struct._ZTS16RegisterBaseInit.RegisterBaseInit // CHECK-NOT: @_ZN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = weak_odr addrspace(1) global %struct._ZTS16RegisterBaseInit.RegisterBaseInit zeroinitializer, comdat, align 1 // CHECK-NOT: @_ZGVN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = weak_odr global i64 0, comdat($_ZN8BaseInitI12TestBaseTypeE9s_regbaseE), align 8 // CHECK: define spir_kernel void @_ZTSZ4mainE11fake_kernel() -// CHECK: call spir_func void @"_ZZ4mainENK3$_0clE16RegisterBaseInit -// CHECK: declare spir_func void @_ZN16RegisterBaseInit3fooEv +// CHECK: call spir_func void @"_ZZ4mainENK3$_0clEv struct TestBaseType {}; struct RegisterBaseInit { @@ -32,11 +29,10 @@ const int BaseInit::var = 9; template struct BaseInit; template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { - kernelFunc(BaseInit::s_regbase); + kernelFunc(); } int main() { - kernel_single_task([=](RegisterBaseInit s) { - s.foo(); + kernel_single_task([=]() { }); return 0; } diff --git a/clang/test/SemaSYCL/sycl-device-const-static.cpp b/clang/test/SemaSYCL/sycl-device-const-static.cpp index 359a533e4181b..1df5a0fe34ffb 100644 --- a/clang/test/SemaSYCL/sycl-device-const-static.cpp +++ b/clang/test/SemaSYCL/sycl-device-const-static.cpp @@ -1,26 +1,51 @@ // RUN: %clang_cc1 -fsycl -fsycl-is-device -verify -fsyntax-only %s +struct Base {}; +struct S { + __attribute__((sycl_device)) void foo(); + S(); +}; + +struct T { + const static S s1; +}; +const S T::s1; + +template +struct U { + static const S s2; +}; +template +const S U::s2; + +template struct U; + void usage() { // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} static int s1; const static int cs = 0; constexpr static int ces = 0; + // expected-error@+1{{SYCL kernel cannot use a const static data variable that is neither zero-initialized nor constant-initialized}} + (void)T::s1; } + template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} static int z; + // expected-note-re@+3{{called by 'kernel_single_task}} // expected-note-re@+2{{called by 'kernel_single_task}} - // expected-note-re@+1{{called by 'kernel_single_task}} - kernelFunc(); + // expected-error@+1{{SYCL kernel cannot use a const static data variable that is neither zero-initialized nor constant-initialized}} + kernelFunc(U::s2); } int main() { static int s2; - kernel_single_task([]() { + kernel_single_task([](S s4) { // expected-note@+1{{called by 'operator()'}} usage(); + s4.foo(); // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} static int s3; }); From 5462e21f8ca531dfe1591abbeae4e16336f4730a Mon Sep 17 00:00:00 2001 From: Premanand M Rao Date: Sat, 4 Jul 2020 15:15:25 -0700 Subject: [PATCH 3/5] [SYCL] Do not emit const sdm initializers Const static variables need to be either zero-initialized or constant-initialized. We were emitting initializers for all const static variables before, which needed invalid address space casts from constant-space to private-space. We now diagnose when they are neither zero- nor constant-initialized and used in device code. This change also reverts the address-space cast introduced in https://github.com/intel/llvm/pull/1774 Signed-off-by: Premanand M Rao --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Sema/SemaExpr.cpp | 9 +-- clang/lib/Sema/SemaSYCL.cpp | 6 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +- .../CodeGenSYCL/sycl-device-const-sdm.cpp | 78 ------------------- .../SemaSYCL/sycl-device-const-static.cpp | 15 +++- 7 files changed, 19 insertions(+), 95 deletions(-) delete mode 100644 clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 27b593d923901..621976d7f19bd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10850,7 +10850,7 @@ def err_sycl_restrict : Error< "|call a dllimport function" "|call a variadic function" "|call an undefined function without SYCL_EXTERNAL attribute" - "|use a const static data variable that is neither zero-initialized " + "|use a const static variable that is neither zero-initialized " "nor constant-initialized" "}0">; def err_sycl_virtual_types : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index df3aa9dcb57d2..2862eceade7ef 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12662,7 +12662,7 @@ class Sema final { KernelCallDllimportFunction, KernelCallVariadicFunction, KernelCallUndefinedFunction, - KernelConstStaticDataVariable + KernelConstStaticVariable }; bool isKnownGoodSYCLDecl(const Decl *D); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 41370c4867fa6..cce8b5023b501 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -223,13 +223,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, VD->hasGlobalStorage() && !isa(VD)) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) << Sema::KernelGlobalVariable; - // Disallow const static data members that are not zero-initialized + // Disallow const statics that are not zero-initialized // or constant-initialized - else if (IsConst && VD->isStaticDataMember() && - !VD->isConstexpr() && - !checkAllowedSYCLInitializer(VD, /*checkValueDependent =*/true)) + else if (IsConst && VD->hasGlobalStorage() && !VD->isConstexpr() && + !checkAllowedSYCLInitializer(VD, /*CheckValueDependent =*/true)) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) - << Sema::KernelConstStaticDataVariable; + << Sema::KernelConstStaticVariable; } } diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 9c89b82a9b951..6c0822a3235d7 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -1854,13 +1854,9 @@ bool Sema::checkAllowedSYCLInitializer(VarDecl *VD, bool CheckValueDependent) { const Expr *Init = VD->getInit(); bool ValueDependent = CheckValueDependent && Init->isValueDependent(); - bool isZeroInit = Init && !ValueDependent && - Init->isIntegerConstantExpr(Context) && - Init->EvaluateKnownConstInt(Context) == 0; bool isConstantInit = Init && !ValueDependent && Init->isConstantInitializer(Context, false); - if (!VD->isConstexpr() && Init && !ValueDependent && !isZeroInit && - !isConstantInit) + if (!VD->isConstexpr() && Init && !ValueDependent && !isConstantInit) return false; return true; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8a8859abf8efc..003086123f78a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5104,7 +5104,7 @@ void Sema::InstantiateVariableInitializer( if (getLangOpts().SYCLIsDevice && !checkAllowedSYCLInitializer(Var)) SYCLDiagIfDeviceCode(Var->getLocation(), diag::err_sycl_restrict) - << Sema::KernelConstStaticDataVariable; + << Sema::KernelConstStaticVariable; } /// Instantiate the definition of the given variable from its diff --git a/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp b/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp deleted file mode 100644 index 8ce7470064172..0000000000000 --- a/clang/test/CodeGenSYCL/sycl-device-const-sdm.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -// Tests that static data members that are not constant-initialized are not -// emitted in device code. - -// CHECK:%struct._ZTS1C.C = type { i32, i32 } -// CHECK:%struct._ZTS1D.D = type { i8 } -// CHECK:$_ZN2TTIiE2c1E = comdat any -// CHECK:$_ZN2TTIiE2d1E = comdat any -// CHECK:$_ZN2TTIiE4var1E = comdat any -// CHECK:$_ZN2TTIiE4var3E = comdat any -// CHECK:@_ZN1S2c1E = addrspace(1) constant %struct._ZTS1C.C { i32 2, i32 5 }, align 4 -// CHECK:@_ZN1S2d1E = addrspace(1) constant %struct._ZTS1D.D zeroinitializer, align 1 -// CHECK:@_ZN1S4var1E = addrspace(1) constant i32 1, align 4 -// CHECK:@_ZN1S4var2E = available_externally addrspace(1) constant i32 3, align 4 -// CHECK:@_ZN1S4var3E = addrspace(1) constant i32 4, align 4 -// CHECK:@_ZN2TTIiE2c1E = linkonce_odr addrspace(1) constant %struct._ZTS1C.C { i32 2, i32 5 }, comdat, align 4 -// CHECK:@_ZN2TTIiE2d1E = linkonce_odr addrspace(1) constant %struct._ZTS1D.D zeroinitializer, comdat, align 1 -// CHECK:@_ZN2TTIiE4var1E = linkonce_odr addrspace(1) constant i32 1, comdat, align 4 -// CHECK:@_ZN2TTIiE4var2E = available_externally addrspace(1) constant i32 3, align 4 -// CHECK:@_ZN2TTIiE4var3E = linkonce_odr addrspace(1) constant i32 4, comdat, align 4 -// CHECK-NOT:@llvm.global_ctors = -// CHECK-NOT: addrspacecast -// CHECK: define spir_kernel void @_ZTSZ4mainE11fake_kernel() - -struct TestBaseType {}; -struct C { - int i, j; -}; -struct D { -}; - -struct S { - static const int var1; - static constexpr const int var2 = 3; - static const int var3; - static const C c1; - static const D d1; -}; -const C S::c1{2, 5}; -const int S::var1 = 1; -const int S::var3 = 1 + 3; -const D S::d1; - -template -struct TT { - static const int var1; - static constexpr const int var2 = 3; - static const int var3; - static const C c1; - static const D d1; -}; -template -const C TT::c1{2, 5}; -template -const int TT::var1 = 1; -template -const int TT::var3 = 1 + 3; -template -const D TT::d1; - -template -__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { - kernelFunc(); - (void)S::c1; - (void)S::d1; - (void)S::var1; - (void)S::var2; - (void)S::var3; - (void)TT::c1; - (void)TT::d1; - (void)TT::var1; - (void)TT::var2; - (void)TT::var3; -} -int main() { - kernel_single_task([=]() {}); - return 0; -} diff --git a/clang/test/SemaSYCL/sycl-device-const-static.cpp b/clang/test/SemaSYCL/sycl-device-const-static.cpp index 1df5a0fe34ffb..b2ef8b4cb584c 100644 --- a/clang/test/SemaSYCL/sycl-device-const-static.cpp +++ b/clang/test/SemaSYCL/sycl-device-const-static.cpp @@ -2,8 +2,8 @@ struct Base {}; struct S { - __attribute__((sycl_device)) void foo(); - S(); + void foo() {} + S() {} }; struct T { @@ -20,13 +20,20 @@ const S U::s2; template struct U; +const S s5; + void usage() { // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} static int s1; const static int cs = 0; constexpr static int ces = 0; - // expected-error@+1{{SYCL kernel cannot use a const static data variable that is neither zero-initialized nor constant-initialized}} + static const S s6; + // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} (void)T::s1; + // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} + (void)s5; + // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} + (void)s6; } @@ -36,7 +43,7 @@ __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { static int z; // expected-note-re@+3{{called by 'kernel_single_task}} // expected-note-re@+2{{called by 'kernel_single_task}} - // expected-error@+1{{SYCL kernel cannot use a const static data variable that is neither zero-initialized nor constant-initialized}} + // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} kernelFunc(U::s2); } From bea5db929b4003b451b653ac0f36e9d22f5372cf Mon Sep 17 00:00:00 2001 From: Premanand M Rao Date: Sat, 4 Jul 2020 15:46:37 -0700 Subject: [PATCH 4/5] Fix clang format errors Signed-off-by: Premanand M Rao --- clang/lib/Sema/SemaSYCL.cpp | 4 ++-- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +- clang/test/SemaSYCL/sycl-device-const-static.cpp | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 6c0822a3235d7..758ea5f311f9f 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -1854,8 +1854,8 @@ bool Sema::checkAllowedSYCLInitializer(VarDecl *VD, bool CheckValueDependent) { const Expr *Init = VD->getInit(); bool ValueDependent = CheckValueDependent && Init->isValueDependent(); - bool isConstantInit = Init && !ValueDependent && - Init->isConstantInitializer(Context, false); + bool isConstantInit = + Init && !ValueDependent && Init->isConstantInitializer(Context, false); if (!VD->isConstexpr() && Init && !ValueDependent && !isConstantInit) return false; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 003086123f78a..5a2967cd091f3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5104,7 +5104,7 @@ void Sema::InstantiateVariableInitializer( if (getLangOpts().SYCLIsDevice && !checkAllowedSYCLInitializer(Var)) SYCLDiagIfDeviceCode(Var->getLocation(), diag::err_sycl_restrict) - << Sema::KernelConstStaticVariable; + << Sema::KernelConstStaticVariable; } /// Instantiate the definition of the given variable from its diff --git a/clang/test/SemaSYCL/sycl-device-const-static.cpp b/clang/test/SemaSYCL/sycl-device-const-static.cpp index b2ef8b4cb584c..60749e8a68594 100644 --- a/clang/test/SemaSYCL/sycl-device-const-static.cpp +++ b/clang/test/SemaSYCL/sycl-device-const-static.cpp @@ -36,7 +36,6 @@ void usage() { (void)s6; } - template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { // expected-error@+1{{SYCL kernel cannot use a non-const static data variable}} From 1020a12c92c4f2847470af421aa6dd324d4c67e9 Mon Sep 17 00:00:00 2001 From: Premanand M Rao Date: Mon, 6 Jul 2020 08:19:08 -0700 Subject: [PATCH 5/5] Fix diagnostic message and comment Signed-off-by: Premanand M Rao --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaExpr.cpp | 4 ++-- clang/test/SemaSYCL/sycl-device-const-static.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 621976d7f19bd..80795aa4ee738 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10850,7 +10850,7 @@ def err_sycl_restrict : Error< "|call a dllimport function" "|call a variadic function" "|call an undefined function without SYCL_EXTERNAL attribute" - "|use a const static variable that is neither zero-initialized " + "|use a const static or global variable that is neither zero-initialized " "nor constant-initialized" "}0">; def err_sycl_virtual_types : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index cce8b5023b501..b5dd7a5cfef8d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -223,8 +223,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, VD->hasGlobalStorage() && !isa(VD)) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) << Sema::KernelGlobalVariable; - // Disallow const statics that are not zero-initialized - // or constant-initialized + // Disallow const statics and globals that are not zero-initialized + // or constant-initialized. else if (IsConst && VD->hasGlobalStorage() && !VD->isConstexpr() && !checkAllowedSYCLInitializer(VD, /*CheckValueDependent =*/true)) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) diff --git a/clang/test/SemaSYCL/sycl-device-const-static.cpp b/clang/test/SemaSYCL/sycl-device-const-static.cpp index 60749e8a68594..0e90057c73d60 100644 --- a/clang/test/SemaSYCL/sycl-device-const-static.cpp +++ b/clang/test/SemaSYCL/sycl-device-const-static.cpp @@ -28,11 +28,11 @@ void usage() { const static int cs = 0; constexpr static int ces = 0; static const S s6; - // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} + // expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}} (void)T::s1; - // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} + // expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}} (void)s5; - // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} + // expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}} (void)s6; } @@ -42,7 +42,7 @@ __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { static int z; // expected-note-re@+3{{called by 'kernel_single_task}} // expected-note-re@+2{{called by 'kernel_single_task}} - // expected-error@+1{{SYCL kernel cannot use a const static variable that is neither zero-initialized nor constant-initialized}} + // expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}} kernelFunc(U::s2); }