Skip to content

Commit f29e1cd

Browse files
committed
[SYCL] Make SYCL device compiler less dependent on SYCL accessor
class implementation. Main changes are: 1. In SYCL kernel entry point we initialize accessors through special accessor method __set_pointer. 2. Minor changes in lit tests. 3. Added hack to emit used top-level decls without CallGraph building. Signed-off-by: Vladimir Lazarev <vladimir.lazarev@intel.com>
1 parent 9a282fb commit f29e1cd

File tree

6 files changed

+74
-38
lines changed

6 files changed

+74
-38
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

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

clang/lib/Sema/SemaSYCL.cpp

+52-22
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,15 @@ CompoundStmt *CreateSYCLKernelBody(Sema &S, CXXMemberCallExpr *e,
6262
if (LE) {
6363
// Create Lambda object
6464
CXXRecordDecl *LC = LE->getLambdaClass();
65-
auto Lambda_VD = VarDecl::Create(
65+
auto LambdaVD = VarDecl::Create(
6666
S.Context, DC, SourceLocation(), SourceLocation(), LC->getIdentifier(),
6767
QualType(LC->getTypeForDecl(), 0), LC->getLambdaTypeInfo(), SC_None);
68+
6869
Stmt *DS = new (S.Context)
69-
DeclStmt(DeclGroupRef(Lambda_VD), SourceLocation(), SourceLocation());
70+
DeclStmt(DeclGroupRef(LambdaVD), SourceLocation(), SourceLocation());
7071
BodyStmts.push_back(DS);
71-
auto Lambda_DRE = DeclRefExpr::Create(
72-
S.Context, NestedNameSpecifierLoc(), SourceLocation(), Lambda_VD, false,
72+
auto LambdaDRE = DeclRefExpr::Create(
73+
S.Context, NestedNameSpecifierLoc(), SourceLocation(), LambdaVD, false,
7374
DeclarationNameInfo(), QualType(LC->getTypeForDecl(), 0), VK_LValue);
7475

7576
// Init Lambda fields
@@ -78,37 +79,66 @@ CompoundStmt *CreateSYCLKernelBody(Sema &S, CXXMemberCallExpr *e,
7879
auto TargetFunc = dyn_cast<FunctionDecl>(DC);
7980
auto TargetFuncParam =
8081
TargetFunc->param_begin(); // Iterator to ParamVarDecl (VarDecl)
81-
for (auto CaptureField : LE->captures()) {
82-
VarDecl *CapturedVar =
83-
CaptureField
84-
.getCapturedVar(); // accessor, need to do setInit for this
82+
for (auto Field : LC->fields()) {
8583
QualType ParamType = (*TargetFuncParam)->getOriginalType();
8684
auto DRE = DeclRefExpr::Create(
8785
S.Context, NestedNameSpecifierLoc(), SourceLocation(),
8886
*TargetFuncParam, false, DeclarationNameInfo(), ParamType, VK_LValue);
8987

90-
Expr *Res = ImplicitCastExpr::Create(
91-
S.Context, ParamType, CK_LValueToRValue, DRE, nullptr, VK_RValue);
88+
CXXRecordDecl *CRD = Field->getType()->getAsCXXRecordDecl();
89+
if (CRD) {
90+
llvm::SmallVector<Expr *, 16> ParamStmts;
91+
DeclAccessPair FieldDAP = DeclAccessPair::make(Field, AS_none);
92+
auto AccessorME = MemberExpr::Create(
93+
S.Context, LambdaDRE, false, SourceLocation(),
94+
NestedNameSpecifierLoc(), SourceLocation(), Field, FieldDAP,
95+
DeclarationNameInfo(Field->getDeclName(), SourceLocation()),
96+
nullptr, Field->getType(), VK_LValue, OK_Ordinary);
97+
98+
for (auto Method : CRD->methods()) {
99+
if (Method->getNameInfo().getName().getAsString() ==
100+
"__set_pointer") {
101+
DeclAccessPair MethodDAP = DeclAccessPair::make(Method, AS_none);
102+
auto ME = MemberExpr::Create(
103+
S.Context, AccessorME, false, SourceLocation(),
104+
NestedNameSpecifierLoc(), SourceLocation(), Method, MethodDAP,
105+
Method->getNameInfo(), nullptr, Method->getType(), VK_LValue,
106+
OK_Ordinary);
107+
108+
// Not referenced -> not emitted
109+
S.MarkFunctionReferenced(SourceLocation(), Method, true);
110+
111+
QualType ResultTy = Method->getReturnType();
112+
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
113+
ResultTy = ResultTy.getNonLValueExprType(S.Context);
114+
115+
// __set_pointer needs one parameter
116+
QualType paramTy = (*(Method->param_begin()))->getOriginalType();
92117

93-
Expr *InitCapture = new (S.Context) InitListExpr(
94-
S.Context, SourceLocation(), /*initExprs*/ Res, SourceLocation());
95-
CapturedVar->setInit(InitCapture);
96-
InitCapture->setType(CapturedVar->getType());
97-
InitCaptures.push_back(InitCapture);
118+
// C++ address space attribute != opencl address space attribute
119+
Expr *qualifiersCast = ImplicitCastExpr::Create(
120+
S.Context, paramTy, CK_NoOp, DRE, nullptr, VK_LValue);
121+
Expr *Res =
122+
ImplicitCastExpr::Create(S.Context, paramTy, CK_LValueToRValue,
123+
qualifiersCast, nullptr, VK_RValue);
124+
125+
ParamStmts.push_back(Res);
126+
127+
// lambda.accessor.__set_pointer(kernel_parameter)
128+
CXXMemberCallExpr *Call = CXXMemberCallExpr::Create(
129+
S.Context, ME, ParamStmts, ResultTy, VK, SourceLocation());
130+
BodyStmts.push_back(Call);
131+
}
132+
}
133+
}
98134
TargetFuncParam++;
99135
}
100136

101-
Expr *InitLambdaCaptures = new (S.Context)
102-
InitListExpr(S.Context, SourceLocation(), /*initExprs*/ InitCaptures,
103-
SourceLocation());
104-
InitLambdaCaptures->setType(Lambda_VD->getType());
105-
Lambda_VD->setInit(InitLambdaCaptures);
106-
107137
// Create Lambda operator () call
108138
FunctionDecl *LO = LE->getCallOperator();
109139
ArrayRef<ParmVarDecl *> Args = LO->parameters();
110140
llvm::SmallVector<Expr *, 16> ParamStmts(1);
111-
ParamStmts[0] = dyn_cast<Expr>(Lambda_DRE);
141+
ParamStmts[0] = dyn_cast<Expr>(LambdaDRE);
112142

113143
// Collect arguments for () operator
114144
for (auto Arg : Args) {

clang/test/CodeGenSYCL/kernel-metadata.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// RUN: %clang -cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
1+
// RUN: %clang -cc1 -DCL_TARGET_OPENCL_VERSION=220 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
22

33
// CHECK: define {{.*}}spir_kernel void @kernel_function() {{[^{]+}} !kernel_arg_addr_space ![[MD:[0-9]+]] !kernel_arg_access_qual ![[MD]] !kernel_arg_type ![[MD]] !kernel_arg_base_type ![[MD]] !kernel_arg_type_qual ![[MD]] {
44
// CHECK: ![[MD]] = !{}
5-
// XFAIL: *
5+
6+
// XFAIL:*
67

78
#include <CL/sycl.hpp>
89

clang/test/CodeGenSYCL/kernel-with-id.cpp

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
// RUN: %clang -cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
2-
// XFAIL: *
3-
#include <CL/sycl.hpp>
1+
// RUN: %clang -cc1 -DCL_TARGET_OPENCL_VERSION=220 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
2+
3+
// XFAIL:*
44

5+
#include <CL/sycl.hpp>
56
#include <array>
67

7-
constexpr cl::sycl::access::mode sycl_read = cl::sycl::access::mode::read;
8-
constexpr cl::sycl::access::mode sycl_write = cl::sycl::access::mode::write;
8+
99

1010
int main() {
1111
const size_t array_size = 1;
@@ -15,10 +15,11 @@ int main() {
1515
cl::sycl::buffer<cl::sycl::cl_int, 1> bufferA(A.data(), numOfItems);
1616

1717
deviceQueue.submit([&](cl::sycl::handler &cgh) {
18-
auto accessorA = bufferA.template get_access<sycl_read>(cgh);
19-
// CHECK: %wiID = alloca %"struct.cl::sycl::id", align 8
20-
// CHECK: call spir_func void @"_ZZZ4mainENK3$_0clERN2cl4sycl7handlerEENKUlNS1_2idILm1EEEE_clES5_"(%class.anon* %0, %"struct.cl::sycl::id"* byval align 8 %wiID)
21-
// CHECK: %call = call spir_func i64 @_Z13get_global_idj(i32 0)
18+
auto accessorA = bufferA.template get_access<cl::sycl::access::mode::read_write>(cgh);
19+
// CHECK: %wiID = alloca %"struct.cl::sycl::id", align 8
20+
// CHECK: call spir_func void @_ZN2cl4sycl8accessorIiLi1ELNS0_6access4modeE1026ELNS2_6targetE2014ELNS2_11placeholderE0EE13__set_pointerEPU3AS1i(%"class.cl::sycl::accessor"* %1, i32 addrspace(1)* %2)
21+
// CHECK: call spir_func void @"_ZZZ4mainENK3$_0clERN2cl4sycl7handlerEENKUlNS1_2idILm1EEEE_clES5_"(%class.anon* %0, %"struct.cl::sycl::id"* byval align 8 %wiID)
22+
// CHECK: %call = call spir_func i64 @_Z13get_global_idj(i32 0)
2223
cgh.parallel_for<class kernel_function>(numOfItems,
2324
[=](cl::sycl::id<1> wiID) {
2425
accessorA[wiID] = accessorA[wiID] * accessorA[wiID];

clang/test/CodeGenSYCL/spir-calling-conv.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang -cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
1+
// RUN: %clang -cc1 -DCL_TARGET_OPENCL_VERSION=220 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
22

3-
// XFAIL: *
3+
// XFAIL:*
44

55
#include <CL/sycl.hpp>
66

clang/test/CodeGenSYCL/spir-opencl-version.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// RUN: %clang -cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
1+
// RUN: %clang -cc1 -DCL_TARGET_OPENCL_VERSION=220 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -S -I /sycl_include_path -I /opencl_include_path -I /usr/include/c++/4.8.5 -I /usr/include/c++/4.8.5/x86_64-redhat-linux -I /usr/include/c++/4.8.5/backward -I /include -I /usr/include -fcxx-exceptions -fexceptions -emit-llvm -x c++ %s -o - | FileCheck %s
22

3-
// XFAIL: *
3+
// XFAIL:*
44

55
#include <CL/sycl.hpp>
66

0 commit comments

Comments
 (0)