Skip to content

Commit 124a88a

Browse files
committed
[SYCL] Mark functions that the kernels call with SYCL device attribute.
Signed-off-by: Vladimir Lazarev <[email protected]>
1 parent 9e3fcc9 commit 124a88a

File tree

3 files changed

+62
-5
lines changed

3 files changed

+62
-5
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,11 +2878,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
28782878
// Look for a declaration that's lexically in a record.
28792879
for (const auto *FD = cast<FunctionDecl>(D)->getMostRecentDecl(); FD;
28802880
FD = FD->getPreviousDecl()) {
2881-
// For SYCL we also should emit a definition for a function because all
2882-
// top-level declarations without OpenCL kernel attribute are ignored
2883-
// now.
2884-
// TODO: fix this hack
2885-
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext()) || LangOpts.SYCL) {
2881+
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) {
28862882
if (FD->doesThisDeclarationHaveABody()) {
28872883
addDeferredDeclToEmit(GD.getWithDecl(FD));
28882884
break;

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/Sema/Sema.h"
1414
#include "llvm/ADT/SmallVector.h"
1515
#include "TreeTransform.h"
16+
#include "clang/AST/RecursiveASTVisitor.h"
1617

1718
using namespace clang;
1819

@@ -28,6 +29,35 @@ enum target {
2829
image_array
2930
};
3031

32+
class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
33+
public:
34+
MarkDeviceFunction(Sema &S)
35+
: RecursiveASTVisitor<MarkDeviceFunction>(), SemaRef(S) {}
36+
bool VisitCallExpr(CallExpr *e) {
37+
if (FunctionDecl *Callee = e->getDirectCallee()) {
38+
// Remember that all SYCL kernel functions have deferred
39+
// instantiation as template functions. It means that
40+
// all functions used by kernel have already been parsed and have
41+
// definitions.
42+
if (FunctionDecl *Def = Callee->getDefinition()) {
43+
if (!Def->hasAttr<SYCLDeviceAttr>()) {
44+
Def->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context));
45+
this->TraverseStmt(Def->getBody());
46+
// But because parser works with top level decls and codegen
47+
// already saw and ignored our function without device attribute we
48+
// need to add this function into sycl kernels array to show it
49+
// this function again.
50+
SemaRef.AddSyclKernel(Def);
51+
}
52+
}
53+
}
54+
return true;
55+
}
56+
57+
private:
58+
Sema &SemaRef;
59+
};
60+
3161
class KernelBodyTransform : public TreeTransform<KernelBodyTransform> {
3262
public:
3363
KernelBodyTransform(llvm::DenseMap<DeclaratorDecl *, DeclaratorDecl *> &Map,
@@ -302,6 +332,10 @@ void Sema::ConstructSYCLKernel(FunctionDecl *KernelHelper) {
302332
SYCLKernel->setBody(SYCLKernelBody);
303333

304334
AddSyclKernel(SYCLKernel);
335+
336+
// Let's mark all called functions with SYCL Device attribute.
337+
MarkDeviceFunction Marker(*this);
338+
Marker.TraverseStmt(SYCLKernelBody);
305339
}
306340
}
307341

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang -cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -emit-llvm -x c++ %s -o - | FileCheck %s
2+
3+
template <typename T>
4+
T bar(T arg);
5+
6+
void foo() {
7+
int a = 1 + 1 + bar(1);
8+
}
9+
10+
template <typename T>
11+
T bar(T arg) {
12+
return arg;
13+
}
14+
15+
template <typename name, typename Func>
16+
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
17+
kernelFunc();
18+
}
19+
20+
int main() {
21+
kernel_single_task<class fake_kernel>([]() { foo(); });
22+
return 0;
23+
}
24+
// CHECK: define spir_kernel void @fake_kernel()
25+
// CHECK: define internal spir_func void @"_ZZ4mainENK3$_0clEv"(%class.anon* %this)
26+
// CHECK: define spir_func void @_Z3foov()
27+
// CHECK: define linkonce_odr spir_func i32 @_Z3barIiET_S0_(i32 %arg)

0 commit comments

Comments
 (0)