Skip to content

Commit bde1085

Browse files
authored
[SYCL] Do not emit const static data members that are not const-initialized (#2019)
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 88d2031 Signed-off-by: Premanand M Rao <[email protected]>
1 parent 80b2110 commit bde1085

File tree

8 files changed

+76
-16
lines changed

8 files changed

+76
-16
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10905,6 +10905,8 @@ def err_sycl_restrict : Error<
1090510905
"|call a dllimport function"
1090610906
"|call a variadic function"
1090710907
"|call an undefined function without SYCL_EXTERNAL attribute"
10908+
"|use a const static or global variable that is neither zero-initialized "
10909+
"nor constant-initialized"
1090810910
"}0">;
1090910911
def err_sycl_virtual_types : Error<
1091010912
"No class with a vtable can be used in a SYCL kernel or any code included in the kernel">;

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9967,6 +9967,8 @@ class Sema final {
99679967
void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *ID);
99689968

99699969
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
9970+
bool checkAllowedSYCLInitializer(VarDecl *VD,
9971+
bool CheckValueDependent = false);
99709972

99719973
// Adds an intel_reqd_sub_group_size attribute to a particular declaration.
99729974
void addIntelReqdSubGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
@@ -12686,7 +12688,8 @@ class Sema final {
1268612688
KernelUseAssembly,
1268712689
KernelCallDllimportFunction,
1268812690
KernelCallVariadicFunction,
12689-
KernelCallUndefinedFunction
12691+
KernelCallUndefinedFunction,
12692+
KernelConstStaticVariable
1269012693
};
1269112694

1269212695
bool isKnownGoodSYCLDecl(const Decl *D);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,8 +1288,7 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
12881288
ctor.addInt(Int32Ty, I.Priority);
12891289
ctor.add(llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy));
12901290
if (I.AssociatedData)
1291-
ctor.add(llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
1292-
I.AssociatedData, VoidPtrTy));
1291+
ctor.add(llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy));
12931292
else
12941293
ctor.addNullPointer(VoidPtrTy);
12951294
ctor.finishAndAddTo(ctors);

clang/lib/Sema/SemaExpr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
223223
VD->hasGlobalStorage() && !isa<ParmVarDecl>(VD))
224224
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
225225
<< Sema::KernelGlobalVariable;
226+
// Disallow const statics and globals that are not zero-initialized
227+
// or constant-initialized.
228+
else if (IsConst && VD->hasGlobalStorage() && !VD->isConstexpr() &&
229+
!checkAllowedSYCLInitializer(VD, /*CheckValueDependent =*/true))
230+
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
231+
<< Sema::KernelConstStaticVariable;
226232
}
227233
}
228234

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,23 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller,
20762076
}
20772077
}
20782078

2079+
bool Sema::checkAllowedSYCLInitializer(VarDecl *VD, bool CheckValueDependent) {
2080+
assert(getLangOpts().SYCLIsDevice &&
2081+
"Should only be called during SYCL compilation");
2082+
2083+
if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage())
2084+
return true;
2085+
2086+
const Expr *Init = VD->getInit();
2087+
bool ValueDependent = CheckValueDependent && Init->isValueDependent();
2088+
bool isConstantInit =
2089+
Init && !ValueDependent && Init->isConstantInitializer(Context, false);
2090+
if (!VD->isConstexpr() && Init && !ValueDependent && !isConstantInit)
2091+
return false;
2092+
2093+
return true;
2094+
}
2095+
20792096
// -----------------------------------------------------------------------------
20802097
// Integration header functionality implementation
20812098
// -----------------------------------------------------------------------------

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5103,6 +5103,10 @@ void Sema::InstantiateVariableInitializer(
51035103

51045104
if (getLangOpts().CUDA)
51055105
checkAllowedCUDAInitializer(Var);
5106+
5107+
if (getLangOpts().SYCLIsDevice && !checkAllowedSYCLInitializer(Var))
5108+
SYCLDiagIfDeviceCode(Var->getLocation(), diag::err_sycl_restrict)
5109+
<< Sema::KernelConstStaticVariable;
51065110
}
51075111

51085112
/// Instantiate the definition of the given variable from its
@@ -5257,7 +5261,10 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
52575261
// Do not explicitly emit non-const static data member definitions
52585262
// on SYCL device.
52595263
if (!SemaRef.getLangOpts().SYCLIsDevice || !Var->isStaticDataMember() ||
5260-
Var->isConstexpr() || Var->getType().isConstQualified())
5264+
Var->isConstexpr() ||
5265+
(Var->getType().isConstQualified() && Var->getInit() &&
5266+
Var->getInit()->isConstantInitializer(SemaRef.getASTContext(),
5267+
false)))
52615268
Consumer.HandleCXXStaticMemberVarInstantiation(Var);
52625269
}
52635270
} PassToConsumerRAII(*this, Consumer, Var);

clang/test/CodeGenSYCL/sycl-device-static-init.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s
22
// Test that static initializers do not force the emission of globals on sycl device
33

4-
// CHECK: %struct._ZTS16RegisterBaseInit.RegisterBaseInit = type { i8 }
54
// CHECK-NOT: $_ZN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = comdat any
65
// CHECK: $_ZN8BaseInitI12TestBaseTypeE3varE = comdat any
7-
// CHECK: @_ZN8BaseInitI12TestBaseTypeE9s_regbaseE = {{.*}} global %struct._ZTS16RegisterBaseInit.RegisterBaseInit
8-
// CHECK-NOT: @_ZN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = weak_odr addrspace(1) global %struct._ZTS16RegisterBaseInit.RegisterBaseInit zeroinitializer, comdat, align 1
96
// CHECK: @_ZN8BaseInitI12TestBaseTypeE3varE = weak_odr addrspace(1) constant i32 9, comdat, align 4
10-
// 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*) }]
7+
// CHECK-NOT: @_ZN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = weak_odr addrspace(1) global %struct._ZTS16RegisterBaseInit.RegisterBaseInit zeroinitializer, comdat, align 1
118
// CHECK-NOT: @_ZGVN8BaseInitI12TestBaseTypeE15s_regbase_ncsdmE = weak_odr global i64 0, comdat($_ZN8BaseInitI12TestBaseTypeE9s_regbaseE), align 8
129
// CHECK: define spir_kernel void @_ZTSZ4mainE11fake_kernel()
13-
// CHECK: call spir_func void @"_ZZ4mainENK3$_0clE16RegisterBaseInit
14-
// CHECK: declare spir_func void @_ZN16RegisterBaseInit3fooEv
10+
// CHECK: call spir_func void @"_ZZ4mainENK3$_0clEv
1511

1612
struct TestBaseType {};
1713
struct RegisterBaseInit {
@@ -33,11 +29,10 @@ const int BaseInit<T>::var = 9;
3329
template struct BaseInit<TestBaseType>;
3430
template <typename name, typename Func>
3531
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
36-
kernelFunc(BaseInit<TestBaseType>::s_regbase);
32+
kernelFunc();
3733
}
3834
int main() {
39-
kernel_single_task<class fake_kernel>([=](RegisterBaseInit s) {
40-
s.foo();
35+
kernel_single_task<class fake_kernel>([=]() {
4136
});
4237
return 0;
4338
}

clang/test/SemaSYCL/sycl-device-const-static.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,57 @@
11
// RUN: %clang_cc1 -fsycl -fsycl-is-device -verify -fsyntax-only %s
22

3+
struct Base {};
4+
struct S {
5+
void foo() {}
6+
S() {}
7+
};
8+
9+
struct T {
10+
const static S s1;
11+
};
12+
const S T::s1;
13+
14+
template <typename T>
15+
struct U {
16+
static const S s2;
17+
};
18+
template <class T>
19+
const S U<T>::s2;
20+
21+
template struct U<Base>;
22+
23+
const S s5;
24+
325
void usage() {
426
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
527
static int s1;
628
const static int cs = 0;
729
constexpr static int ces = 0;
30+
static const S s6;
31+
// expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}}
32+
(void)T::s1;
33+
// expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}}
34+
(void)s5;
35+
// expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}}
36+
(void)s6;
837
}
938

1039
template <typename Name, typename Func>
1140
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
1241
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
1342
static int z;
43+
// expected-note-re@+3{{called by 'kernel_single_task<fake_kernel, (lambda at {{.*}})>}}
1444
// expected-note-re@+2{{called by 'kernel_single_task<fake_kernel, (lambda at {{.*}})>}}
15-
// expected-note-re@+1{{called by 'kernel_single_task<fake_kernel, (lambda at {{.*}})>}}
16-
kernelFunc();
45+
// expected-error@+1{{SYCL kernel cannot use a const static or global variable that is neither zero-initialized nor constant-initialized}}
46+
kernelFunc(U<Base>::s2);
1747
}
1848

1949
int main() {
2050
static int s2;
21-
kernel_single_task<class fake_kernel>([]() {
51+
kernel_single_task<class fake_kernel>([](S s4) {
2252
// expected-note@+1{{called by 'operator()'}}
2353
usage();
54+
s4.foo();
2455
// expected-error@+1{{SYCL kernel cannot use a non-const static data variable}}
2556
static int s3;
2657
});

0 commit comments

Comments
 (0)