Skip to content

Commit b671be9

Browse files
[SYCL]Emit an error if array size exceeds 65532 for SPIRV targets
* Due to SPIR-V intermediate format limitations, const global arrays with number of elements more than 65532 cannot be used inside SYCL kernel. * A possible workaround is to split the array into several ones.
1 parent 363ad5f commit b671be9

File tree

5 files changed

+54
-0
lines changed

5 files changed

+54
-0
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10908,6 +10908,9 @@ def err_sycl_restrict : Error<
1090810908
"|use a const static or global variable that is neither zero-initialized "
1090910909
"nor constant-initialized"
1091010910
"}0">;
10911+
def err_array_num_elements_exceeded
10912+
: Error<"Due to SPIR-V intermediate format limitations, constant arrays with number of elements more than 65532 cannot be used in SYCL."
10913+
"You can workaround this limitation by splitting the array into several ones">;
1091110914
def err_sycl_virtual_types : Error<
1091210915
"No class with a vtable can be used in a SYCL kernel or any code included in the kernel">;
1091310916
def note_sycl_recursive_function_declared_here: Note<"function implemented using recursion declared here">;

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9969,6 +9969,7 @@ class Sema final {
99699969
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
99709970
bool checkAllowedSYCLInitializer(VarDecl *VD,
99719971
bool CheckValueDependent = false);
9972+
bool isArrayZeroInitialized(VarDecl *VD, bool CheckValueDependent = false);
99729973

99739974
// Adds an intel_reqd_sub_group_size attribute to a particular declaration.
99749975
void addIntelReqdSubGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,

clang/lib/Sema/SemaExpr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,21 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
229229
!checkAllowedSYCLInitializer(VD, /*CheckValueDependent =*/true))
230230
SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict)
231231
<< Sema::KernelConstStaticVariable;
232+
// Emit an error if a const global array's size exceeds SPIR-V
233+
// intermediate format limitations for SPIRV compatible devices.
234+
else if (IsConst && VD->hasGlobalStorage() &&
235+
Context.getTargetInfo().getTriple().isSPIR() &&
236+
!isArrayZeroInitialized(VD, /*CheckValueDependent =*/true)) {
237+
QualType Ty = VD->getType();
238+
if (const auto *CAType = dyn_cast<ConstantArrayType>(Ty)) {
239+
assert(CAType);
240+
const int MaxNumElements = 65535 - 3;
241+
int64_t arrayElements = CAType->getSize().getSExtValue();
242+
if (arrayElements > MaxNumElements)
243+
SYCLDiagIfDeviceCode(*Locs.begin(),
244+
diag::err_array_num_elements_exceeded);
245+
}
246+
}
232247
}
233248
}
234249

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,22 @@ void Sema::finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller,
20772077
}
20782078
}
20792079

2080+
bool Sema::isArrayZeroInitialized(VarDecl *VD, bool CheckValueDependent) {
2081+
assert(getLangOpts().SYCLIsDevice &&
2082+
"Should only be called during device compilation");
2083+
if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage())
2084+
return false;
2085+
APValue *Value = nullptr;
2086+
if (VD->getInit() && !VD->getInit()->isValueDependent())
2087+
Value = VD->evaluateValue();
2088+
// zero-initialized arrays do not have any initialized elements.
2089+
if (Value && Value->isArray() && Value->hasArrayFiller() &&
2090+
Value->getArrayInitializedElts() == 0) {
2091+
return true;
2092+
}
2093+
return false;
2094+
}
2095+
20802096
bool Sema::checkAllowedSYCLInitializer(VarDecl *VD, bool CheckValueDependent) {
20812097
assert(getLangOpts().SYCLIsDevice &&
20822098
"Should only be called during SYCL compilation");
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir-unknown -verify -fsyntax-only %s
2+
// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown -verify -fsyntax-only %s
3+
4+
const double big[67000] = {1.0, 2.0, 3.0};
5+
const int zero_init_array[67000] = {};
6+
7+
template <typename Name, typename Func>
8+
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
9+
kernelFunc(); // expected-note {{called by 'kernel_single_task<fake_kernel, (lambda}}
10+
}
11+
12+
int main() {
13+
double hostResult = big[0]; // no error thrown, since accessing global const arrays with size > 65532 is valid from host code.
14+
kernel_single_task<class fake_kernel>([]() {
15+
int a = zero_init_array[0]; // no error thrown, since accessing zero-initialized arrays with size > 65532 is valid.
16+
double kernelGlobal = big[0]; // expected-error {{Due to SPIR-V intermediate format limitations, constant arrays with number of elements more than 65532 cannot be used in SYCL.You can workaround this limitation by splitting the array into several ones}}
17+
});
18+
return 0;
19+
}

0 commit comments

Comments
 (0)