Skip to content

Commit ef90e6a

Browse files
authored
[SYCL] Store the kernel object size in the integration header (#5862)
Sometimes when the host compiler is different from the device compiler, it is possible that the size of the kernel object on the host will differ from the size of the kernel object on the device. One such case is when constexpr variables are used; compilers differ on whether they need to be captured and this causes a discrepancy in the size of the kernel object and leads to failures at runtime. This change adds an interface to the integration header which returns the size of the kernel object as computed on the device. The expectation is that the library will assert the size of a kernel when compiling the host to detect potential mismatches.
1 parent eaf8b42 commit ef90e6a

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ class SYCLIntegrationHeader {
335335
/// Signals that subsequent parameter descriptor additions will go to
336336
/// the kernel with given name. Starts new kernel invocation descriptor.
337337
void startKernel(const FunctionDecl *SyclKernel, QualType KernelNameType,
338-
SourceLocation Loc, bool IsESIMD, bool IsUnnamedKernel);
338+
SourceLocation Loc, bool IsESIMD, bool IsUnnamedKernel,
339+
int64_t ObjSize);
339340

340341
/// Adds a kernel parameter descriptor to current kernel invocation
341342
/// descriptor.
@@ -409,10 +410,15 @@ class SYCLIntegrationHeader {
409410
// hasn't provided an explicit name for.
410411
bool IsUnnamedKernel;
411412

413+
/// Size of the kernel object.
414+
int64_t ObjSize = 0;
415+
412416
KernelDesc(const FunctionDecl *SyclKernel, QualType NameType,
413-
SourceLocation KernelLoc, bool IsESIMD, bool IsUnnamedKernel)
417+
SourceLocation KernelLoc, bool IsESIMD, bool IsUnnamedKernel,
418+
int64_t ObjSize)
414419
: SyclKernel(SyclKernel), NameType(NameType), KernelLocation(KernelLoc),
415-
IsESIMDKernel(IsESIMD), IsUnnamedKernel(IsUnnamedKernel) {}
420+
IsESIMDKernel(IsESIMD), IsUnnamedKernel(IsUnnamedKernel),
421+
ObjSize(ObjSize) {}
416422

417423
void updateKernelNames(StringRef Name, StringRef StableName) {
418424
this->Name = Name.str();

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3124,8 +3124,13 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler {
31243124
FunctionDecl *KernelFunc)
31253125
: SyclKernelFieldHandler(S), Header(H) {
31263126
bool IsSIMDKernel = isESIMDKernelType(KernelObj);
3127+
// The header needs to access the kernel object size.
3128+
int64_t ObjSize = SemaRef.getASTContext()
3129+
.getTypeSizeInChars(KernelObj->getTypeForDecl())
3130+
.getQuantity();
31273131
Header.startKernel(KernelFunc, NameType, KernelObj->getLocation(),
3128-
IsSIMDKernel, IsSYCLUnnamedKernel(S, KernelFunc));
3132+
IsSIMDKernel, IsSYCLUnnamedKernel(S, KernelFunc),
3133+
ObjSize);
31293134
}
31303135

31313136
bool handleSyclSpecialType(const CXXRecordDecl *RD,
@@ -4777,6 +4782,14 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {
47774782
O << " return 0;\n";
47784783
O << "#endif\n";
47794784
O << " }\n";
4785+
StringRef ReturnType =
4786+
(S.Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong)
4787+
? "long"
4788+
: "long long";
4789+
O << " // Returns the size of the kernel object in bytes.\n";
4790+
O << " __SYCL_DLL_LOCAL\n";
4791+
O << " static constexpr " << ReturnType << " getKernelSize() { return "
4792+
<< K.ObjSize << "; }\n";
47804793
O << "};\n";
47814794
CurStart += N;
47824795
}
@@ -4807,9 +4820,9 @@ void SYCLIntegrationHeader::startKernel(const FunctionDecl *SyclKernel,
48074820
QualType KernelNameType,
48084821
SourceLocation KernelLocation,
48094822
bool IsESIMDKernel,
4810-
bool IsUnnamedKernel) {
4823+
bool IsUnnamedKernel, int64_t ObjSize) {
48114824
KernelDescs.emplace_back(SyclKernel, KernelNameType, KernelLocation,
4812-
IsESIMDKernel, IsUnnamedKernel);
4825+
IsESIMDKernel, IsUnnamedKernel, ObjSize);
48134826
}
48144827

48154828
void SYCLIntegrationHeader::addParamDesc(kernel_param_kind_t Kind, int Info,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -fsycl-int-header=%t.h %s
2+
// RUN: FileCheck -input-file=%t.h %s
3+
4+
// This test checks that the getKernelSize() member function is
5+
// generated into the integration header and that it returns the
6+
// size of the kernel object in bytes.
7+
8+
#include "sycl.hpp"
9+
10+
using namespace cl::sycl;
11+
12+
void testA() {
13+
queue q;
14+
constexpr int N = 256;
15+
int A[N] = {10};
16+
q.submit([&](handler &h) {
17+
h.single_task<class KernelName>([=]() {
18+
for (int k = 0; k < N; ++k) {
19+
(void)A[k];
20+
}
21+
});
22+
});
23+
}
24+
// CHECK: template <> struct KernelInfo<KernelName> {
25+
// CHECK: // Returns the size of the kernel object in bytes.
26+
// CHECK: static constexpr long{{.*}} getKernelSize() { return 1024; }

0 commit comments

Comments
 (0)