Skip to content

Commit

Permalink
[SYCL] Mark functions that the kernels call with SYCL device attribute.
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Lazarev <vladimir.lazarev@intel.com>
  • Loading branch information
vladimirlaz committed Jan 22, 2019
1 parent 9e3fcc9 commit 124a88a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
6 changes: 1 addition & 5 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2878,11 +2878,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
// Look for a declaration that's lexically in a record.
for (const auto *FD = cast<FunctionDecl>(D)->getMostRecentDecl(); FD;
FD = FD->getPreviousDecl()) {
// For SYCL we also should emit a definition for a function because all
// top-level declarations without OpenCL kernel attribute are ignored
// now.
// TODO: fix this hack
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext()) || LangOpts.SYCL) {
if (isa<CXXRecordDecl>(FD->getLexicalDeclContext())) {
if (FD->doesThisDeclarationHaveABody()) {
addDeferredDeclToEmit(GD.getWithDecl(FD));
break;
Expand Down
34 changes: 34 additions & 0 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "clang/Sema/Sema.h"
#include "llvm/ADT/SmallVector.h"
#include "TreeTransform.h"
#include "clang/AST/RecursiveASTVisitor.h"

using namespace clang;

Expand All @@ -28,6 +29,35 @@ enum target {
image_array
};

class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
public:
MarkDeviceFunction(Sema &S)
: RecursiveASTVisitor<MarkDeviceFunction>(), SemaRef(S) {}
bool VisitCallExpr(CallExpr *e) {
if (FunctionDecl *Callee = e->getDirectCallee()) {
// Remember that all SYCL kernel functions have deferred
// instantiation as template functions. It means that
// all functions used by kernel have already been parsed and have
// definitions.
if (FunctionDecl *Def = Callee->getDefinition()) {
if (!Def->hasAttr<SYCLDeviceAttr>()) {
Def->addAttr(SYCLDeviceAttr::CreateImplicit(SemaRef.Context));
this->TraverseStmt(Def->getBody());
// But because parser works with top level decls and codegen
// already saw and ignored our function without device attribute we
// need to add this function into sycl kernels array to show it
// this function again.
SemaRef.AddSyclKernel(Def);
}
}
}
return true;
}

private:
Sema &SemaRef;
};

class KernelBodyTransform : public TreeTransform<KernelBodyTransform> {
public:
KernelBodyTransform(llvm::DenseMap<DeclaratorDecl *, DeclaratorDecl *> &Map,
Expand Down Expand Up @@ -302,6 +332,10 @@ void Sema::ConstructSYCLKernel(FunctionDecl *KernelHelper) {
SYCLKernel->setBody(SYCLKernelBody);

AddSyclKernel(SYCLKernel);

// Let's mark all called functions with SYCL Device attribute.
MarkDeviceFunction Marker(*this);
Marker.TraverseStmt(SYCLKernelBody);
}
}

27 changes: 27 additions & 0 deletions clang/test/CodeGenSYCL/device-functions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// RUN: %clang -cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -emit-llvm -x c++ %s -o - | FileCheck %s

template <typename T>
T bar(T arg);

void foo() {
int a = 1 + 1 + bar(1);
}

template <typename T>
T bar(T arg) {
return arg;
}

template <typename name, typename Func>
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
kernelFunc();
}

int main() {
kernel_single_task<class fake_kernel>([]() { foo(); });
return 0;
}
// CHECK: define spir_kernel void @fake_kernel()
// CHECK: define internal spir_func void @"_ZZ4mainENK3$_0clEv"(%class.anon* %this)
// CHECK: define spir_func void @_Z3foov()
// CHECK: define linkonce_odr spir_func i32 @_Z3barIiET_S0_(i32 %arg)

0 comments on commit 124a88a

Please sign in to comment.