Skip to content

Commit db492bd

Browse files
committed
Decomposed array elements, and changed manner of array element initialization.
1 parent d5fb2d9 commit db492bd

File tree

8 files changed

+290
-574
lines changed

8 files changed

+290
-574
lines changed

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 82 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -791,18 +791,23 @@ static void VisitField(CXXRecordDecl *Owner, RangeTy &&Item, QualType ItemTy,
791791
else if (ItemTy->isStructureOrClassType())
792792
VisitAccessorWrapper(Owner, Item, ItemTy->getAsCXXRecordDecl(),
793793
handlers...);
794-
#if 0
795-
// FIXME Enable this when structs are replaced by their fields
794+
// FIXME Enable this when structs are replaced by their fields
795+
#define STRUCTS_DECOMPOSED 0
796+
#if STRUCTS_DECOMPOSED
796797
else if (ItemTy->isArrayType())
797798
VisitArrayElements(Item, ItemTy, handlers...);
798-
#endif
799+
else if (ItemTy->isScalarType())
800+
KF_FOR_EACH(handleScalarType, Item, ItemTy);
801+
}
802+
#else
799803
}
800804

801805
template <typename RangeTy, typename... Handlers>
802806
static void VisitScalarField(CXXRecordDecl *Owner, RangeTy &&Item,
803807
QualType ItemTy, Handlers &... handlers) {
804808
KF_FOR_EACH(handleScalarType, Item, ItemTy);
805809
}
810+
#endif
806811

807812
template <typename RangeTy, typename... Handlers>
808813
static void VisitArrayElements(RangeTy Item, QualType FieldTy,
@@ -812,13 +817,18 @@ static void VisitArrayElements(RangeTy Item, QualType FieldTy,
812817
int64_t ElemCount = CAT->getSize().getSExtValue();
813818
std::initializer_list<int>{(handlers.enterArray(), 0)...};
814819
for (int64_t Count = 0; Count < ElemCount; Count++) {
820+
#if STRUCTS_DECOMPOSED
821+
VisitField(nullptr, Item, ET, handlers...);
822+
#else
815823
if (ET->isScalarType())
816824
VisitScalarField(nullptr, Item, ET, handlers...);
817825
else
818826
VisitField(nullptr, Item, ET, handlers...);
827+
#endif
819828
(void)std::initializer_list<int>{(handlers.nextElement(ET), 0)...};
820829
}
821-
(void)std::initializer_list<int>{(handlers.leaveArray(ET, ElemCount), 0)...};
830+
(void)std::initializer_list<int>{
831+
(handlers.leaveArray(Item, ET, ElemCount), 0)...};
822832
}
823833

824834
template <typename RangeTy, typename... Handlers>
@@ -932,20 +942,31 @@ template <typename Derived> class SyclKernelFieldHandler {
932942
// class/field graph. Int Headers use this to calculate offset, most others
933943
// don't have a need for these.
934944

935-
virtual void enterStruct(const CXXRecordDecl *, FieldDecl *) {}
936-
virtual void leaveStruct(const CXXRecordDecl *, FieldDecl *) {}
937-
virtual void enterStruct(const CXXRecordDecl *, const CXXBaseSpecifier &) {}
938-
virtual void leaveStruct(const CXXRecordDecl *, const CXXBaseSpecifier &) {}
945+
virtual bool enterStruct(const CXXRecordDecl *, FieldDecl *) { return true; }
946+
virtual bool leaveStruct(const CXXRecordDecl *, FieldDecl *) { return true; }
947+
virtual bool enterStruct(const CXXRecordDecl *, const CXXBaseSpecifier &) {
948+
return true;
949+
}
950+
virtual bool leaveStruct(const CXXRecordDecl *, const CXXBaseSpecifier &) {
951+
return true;
952+
}
939953

940954
// The following are used for stepping through array elements.
941955

942-
virtual void enterField(const CXXRecordDecl *, const CXXBaseSpecifier &) {}
943-
virtual void leaveField(const CXXRecordDecl *, const CXXBaseSpecifier &) {}
944-
virtual void enterField(const CXXRecordDecl *, FieldDecl *) {}
945-
virtual void leaveField(const CXXRecordDecl *, FieldDecl *) {}
946-
virtual void enterArray() {}
947-
virtual void nextElement(QualType) {}
948-
virtual void leaveArray(QualType, int64_t) {}
956+
virtual bool enterField(const CXXRecordDecl *, const CXXBaseSpecifier &) {
957+
return true;
958+
}
959+
virtual bool leaveField(const CXXRecordDecl *, const CXXBaseSpecifier &) {
960+
return true;
961+
}
962+
virtual bool enterField(const CXXRecordDecl *, FieldDecl *) { return true; }
963+
virtual bool leaveField(const CXXRecordDecl *, FieldDecl *) { return true; }
964+
virtual bool enterArray() { return true; }
965+
virtual bool nextElement(QualType) { return true; }
966+
virtual bool leaveArray(const CXXBaseSpecifier &, QualType, int64_t) {
967+
return true;
968+
}
969+
virtual bool leaveArray(FieldDecl *, QualType, int64_t) { return true; }
949970
};
950971

951972
// A type to check the validity of all of the argument types.
@@ -1242,6 +1263,7 @@ class SyclKernelBodyCreator
12421263
InitializedEntity VarEntity;
12431264
CXXRecordDecl *KernelObj;
12441265
llvm::SmallVector<Expr *, 16> MemberExprBases;
1266+
uint64_t ArrayIndex;
12451267
FunctionDecl *KernelCallerFunc;
12461268

12471269
// Using the statements/init expressions that we've created, this generates
@@ -1340,30 +1362,27 @@ class SyclKernelBodyCreator
13401362
InitExprs.push_back(MemberInit.get());
13411363
}
13421364

1343-
void createExprForScalarElement(FieldDecl *FD, QualType FieldTy) {
1365+
void createExprForScalarElement(FieldDecl *FD) {
13441366
InitializedEntity ArrayEntity =
13451367
InitializedEntity::InitializeMember(FD, &VarEntity);
13461368
InitializationKind InitKind =
13471369
InitializationKind::CreateCopy(SourceLocation(), SourceLocation());
13481370
Expr *DRE = createInitExpr(FD);
1349-
Expr *Idx = dyn_cast<ArraySubscriptExpr>(MemberExprBases.back())->getIdx();
1350-
llvm::APSInt Result;
1351-
SemaRef.VerifyIntegerConstantExpression(Idx, &Result);
1352-
uint64_t IntIdx = Result.getZExtValue();
13531371
InitializedEntity Entity = InitializedEntity::InitializeElement(
1354-
SemaRef.getASTContext(), IntIdx, ArrayEntity);
1372+
SemaRef.getASTContext(), ArrayIndex, ArrayEntity);
1373+
ArrayIndex++;
13551374
InitializationSequence InitSeq(SemaRef, Entity, InitKind, DRE);
13561375
ExprResult MemberInit = InitSeq.Perform(SemaRef, Entity, InitKind, DRE);
1376+
InitExprs.push_back(MemberInit.get());
1377+
}
1378+
1379+
void addArrayInit(FieldDecl *FD, int64_t Count) {
13571380
llvm::SmallVector<Expr *, 16> ArrayInitExprs;
1358-
if (IntIdx > 0) {
1359-
// Continue with the current InitList
1360-
InitListExpr *ILE = cast<InitListExpr>(InitExprs.back());
1381+
for (int64_t I = 0; I < Count; I++) {
1382+
ArrayInitExprs.push_back(InitExprs.back());
13611383
InitExprs.pop_back();
1362-
llvm::ArrayRef<Expr *> L = ILE->inits();
1363-
for (size_t I = 0; I < L.size(); I++)
1364-
ArrayInitExprs.push_back(L[I]);
13651384
}
1366-
ArrayInitExprs.push_back(MemberInit.get());
1385+
std::reverse(ArrayInitExprs.begin(), ArrayInitExprs.end());
13671386
Expr *ILE = new (SemaRef.getASTContext())
13681387
InitListExpr(SemaRef.getASTContext(), SourceLocation(), ArrayInitExprs,
13691388
SourceLocation());
@@ -1421,8 +1440,10 @@ class SyclKernelBodyCreator
14211440

14221441
bool handleSpecialType(FieldDecl *FD, QualType Ty) {
14231442
const auto *RecordDecl = Ty->getAsCXXRecordDecl();
1424-
// Perform initialization only if it is field of kernel object
1425-
if (MemberExprBases.size() == 2) {
1443+
ArraySubscriptExpr *ArrayRef =
1444+
dyn_cast<ArraySubscriptExpr>(MemberExprBases.back());
1445+
// Perform initialization only if decomposed from array
1446+
if (ArrayRef || MemberExprBases.size() == 2) {
14261447
InitializedEntity Entity =
14271448
InitializedEntity::InitializeMember(FD, &VarEntity);
14281449
// Initialize with the default constructor.
@@ -1507,31 +1528,37 @@ class SyclKernelBodyCreator
15071528

15081529
bool handleScalarType(FieldDecl *FD, QualType FieldTy) final {
15091530
if (dyn_cast<ArraySubscriptExpr>(MemberExprBases.back()))
1510-
createExprForScalarElement(FD, FieldTy);
1531+
createExprForScalarElement(FD);
15111532
else
15121533
createExprForStructOrScalar(FD);
15131534
return true;
15141535
}
15151536

1516-
void enterField(const CXXRecordDecl *RD, FieldDecl *FD) final {
1537+
bool enterField(const CXXRecordDecl *RD, FieldDecl *FD) final {
15171538
if (!FD->getType()->isReferenceType())
15181539
MemberExprBases.push_back(BuildMemberExpr(MemberExprBases.back(), FD));
1540+
return true;
15191541
}
15201542

1521-
void leaveField(const CXXRecordDecl *, FieldDecl *FD) final {
1543+
bool leaveField(const CXXRecordDecl *, FieldDecl *FD) final {
15221544
if (!FD->getType()->isReferenceType())
15231545
MemberExprBases.pop_back();
1546+
return true;
15241547
}
15251548

1526-
void enterArray() final {
1549+
bool enterArray() final {
15271550
Expr *ArrayBase = MemberExprBases.back();
15281551
ExprResult IndexExpr = SemaRef.ActOnIntegerConstant(SourceLocation(), 0);
15291552
ExprResult ElementBase = SemaRef.CreateBuiltinArraySubscriptExpr(
15301553
ArrayBase, SourceLocation(), IndexExpr.get(), SourceLocation());
15311554
MemberExprBases.push_back(ElementBase.get());
1555+
ArrayIndex = 0;
1556+
return true;
15321557
}
15331558

1534-
void nextElement(QualType) final {
1559+
bool nextElement(QualType ET) final {
1560+
if (ET->isScalarType())
1561+
return true;
15351562
ArraySubscriptExpr *LastArrayRef =
15361563
dyn_cast<ArraySubscriptExpr>(MemberExprBases.back());
15371564
MemberExprBases.pop_back();
@@ -1544,14 +1571,20 @@ class SyclKernelBodyCreator
15441571
ExprResult ElementBase = SemaRef.CreateBuiltinArraySubscriptExpr(
15451572
ArrayBase, SourceLocation(), IndexExpr.get(), SourceLocation());
15461573
MemberExprBases.push_back(ElementBase.get());
1574+
return true;
15471575
}
15481576

1549-
void leaveArray(QualType, int64_t) final { MemberExprBases.pop_back(); }
1577+
bool leaveArray(FieldDecl *FD, QualType, int64_t Count) final {
1578+
addArrayInit(FD, Count);
1579+
MemberExprBases.pop_back();
1580+
return true;
1581+
}
15501582

15511583
using SyclKernelFieldHandler::enterArray;
15521584
using SyclKernelFieldHandler::enterField;
15531585
using SyclKernelFieldHandler::handleScalarType;
15541586
using SyclKernelFieldHandler::handleSyclSamplerType;
1587+
using SyclKernelFieldHandler::leaveArray;
15551588
using SyclKernelFieldHandler::leaveField;
15561589
};
15571590

@@ -1670,43 +1703,50 @@ class SyclKernelIntHeaderCreator
16701703
return true;
16711704
}
16721705

1673-
void enterField(const CXXRecordDecl *RD, FieldDecl *FD) final {
1706+
bool enterField(const CXXRecordDecl *RD, FieldDecl *FD) final {
16741707
CurOffset += SemaRef.getASTContext().getFieldOffset(FD) / 8;
1708+
return true;
16751709
}
16761710

1677-
void leaveField(const CXXRecordDecl *, FieldDecl *FD) final {
1711+
bool leaveField(const CXXRecordDecl *, FieldDecl *FD) final {
16781712
CurOffset -= SemaRef.getASTContext().getFieldOffset(FD) / 8;
1713+
return true;
16791714
}
16801715

1681-
void enterField(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS) final {
1716+
bool enterField(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS) final {
16821717
const ASTRecordLayout &Layout =
16831718
SemaRef.getASTContext().getASTRecordLayout(RD);
16841719
CurOffset += Layout.getBaseClassOffset(BS.getType()->getAsCXXRecordDecl())
16851720
.getQuantity();
1721+
return true;
16861722
}
16871723

1688-
void leaveField(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS) final {
1724+
bool leaveField(const CXXRecordDecl *RD, const CXXBaseSpecifier &BS) final {
16891725
const ASTRecordLayout &Layout =
16901726
SemaRef.getASTContext().getASTRecordLayout(RD);
16911727
CurOffset -= Layout.getBaseClassOffset(BS.getType()->getAsCXXRecordDecl())
16921728
.getQuantity();
1729+
return true;
16931730
}
16941731

1695-
void nextElement(QualType ET) final {
1732+
bool nextElement(QualType ET) final {
16961733
CurOffset += SemaRef.getASTContext().getTypeSizeInChars(ET).getQuantity();
1734+
return true;
16971735
}
16981736

1699-
void leaveArray(QualType ET, int64_t Count) final {
1737+
bool leaveArray(FieldDecl *, QualType ET, int64_t Count) final {
17001738
int64_t ArraySize =
17011739
SemaRef.getASTContext().getTypeSizeInChars(ET).getQuantity();
17021740
if (!ET->isArrayType()) {
17031741
ArraySize *= Count;
17041742
}
17051743
CurOffset -= ArraySize;
1744+
return true;
17061745
}
17071746

17081747
using SyclKernelFieldHandler::handleScalarType;
17091748
using SyclKernelFieldHandler::handleSyclSamplerType;
1749+
using SyclKernelFieldHandler::leaveArray;
17101750
};
17111751
} // namespace
17121752

clang/test/CodeGenSYCL/kernel-param-acc-array.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,30 @@ int main() {
4949
// CHECK: [[MEM_RANGE2:%[a-zA-Z0-9_.]+]] = alloca %"struct.{{.*}}.cl::sycl::range"
5050
// CHECK: [[OFFSET2:%[a-zA-Z0-9_.]+]] = alloca %"struct.{{.*}}.cl::sycl::id"
5151

52-
// CHECK accessor array GEP for acc[0]
52+
// CHECK accessor array default inits
5353
// CHECK: [[ACCESSOR_ARRAY1:%[a-zA-Z0-9_]+]] = getelementptr inbounds %"class.{{.*}}.anon", %"class.{{.*}}.anon"* [[LOCAL_OBJECT]], i32 0, i32 0
54-
// CHECK: [[Z0:%[a-zA-Z0-9_]*]] = getelementptr inbounds{{.*}}[[ACCESSOR_ARRAY1]], i64 0, i64 0
54+
// CHECK: [[BEGIN:%[a-zA-Z0-9._]*]] = getelementptr inbounds [2 x [[ACCESSOR:.*]]], [2 x [[ACCESSOR]]]* [[ACCESSOR_ARRAY1]], i64 0, i64 0
55+
// CHECK: [[END:%[a-zA-Z0-9._]*]] = getelementptr inbounds [[ACCESSOR:.*]], [[ACCESSOR]]* [[BEGIN]], i64 2
56+
// CHECK: [[NEXT0:%[a-zA-Z0-9._]*]] = getelementptr inbounds [[ACCESSOR]], [[ACCESSOR]]* {{.*}}, i64 1
57+
// CHECK: [[ELEMENT:%[a-zA-Z0-9._]*]] = getelementptr inbounds [[ACCESSOR]], [[ACCESSOR]]* {{.*}}, i64 1
58+
// CHECK: [[ELEMENT:%[a-zA-Z0-9._]*]] = getelementptr inbounds [[ACCESSOR]], [[ACCESSOR]]* {{.*}}, i64 2
59+
// CHECK: [[NEXT1:%[a-zA-Z0-9._]*]] = getelementptr inbounds [[ACCESSOR]], [[ACCESSOR]]* {{.*}}, i64 1
60+
61+
// CHECK: [[ACCESSOR_ARRAY2:%[a-zA-Z0-9_]+]] = getelementptr inbounds %"class.{{.*}}.anon", %"class.{{.*}}.anon"* [[LOCAL_OBJECT]], i32 0, i32 0
62+
// CHECK: [[INDEX:%[a-zA-Z0-9._]*]] = getelementptr inbounds [2 x [[ACCESSOR]]], [2 x [[ACCESSOR]]]* [[ACCESSOR_ARRAY2]], i64 0, i64 0
5563

5664
// CHECK load from kernel pointer argument alloca
5765
// CHECK: [[MEM_LOAD1:%[a-zA-Z0-9_]+]] = load i32 addrspace(1)*, i32 addrspace(1)** [[MEM_ARG1]]
5866

59-
// CHECK acc[0] __init method call
60-
// CHECK: [[ACC_CAST1:%[0-9]+]] = addrspacecast %"class{{.*}}accessor"* [[Z0]] to %"class{{.*}}accessor" addrspace(4)*
67+
// CHECK: [[ACC_CAST1:%[0-9]+]] = addrspacecast [[ACCESSOR]]* {{.*}} to [[ACCESSOR]] addrspace(4)*
6168

69+
// CHECK acc[0] __init method call
6270
// CHECK: call spir_func void @{{.*}}__init{{.*}}(%"class.{{.*}}.cl::sycl::accessor" addrspace(4)* [[ACC_CAST1]], i32 addrspace(1)* [[MEM_LOAD1]], %"struct.{{.*}}.cl::sycl::range"* byval({{.*}}) align 4 [[ACC_RANGE1]], %"struct.{{.*}}.cl::sycl::range"* byval({{.*}}) align 4 [[MEM_RANGE1]], %"struct.{{.*}}.cl::sycl::id"* byval({{.*}}) align 4 [[OFFSET1]])
6371

64-
// CHECK accessor array GEP for acc[1]
65-
// CHECK: [[ACCESSOR_ARRAY2:%[a-zA-Z0-9_]+]] = getelementptr inbounds %"class.{{.*}}.anon", %"class.{{.*}}.anon"* [[LOCAL_OBJECT]], i32 0, i32 0
66-
// CHECK: [[Z1:%[a-zA-Z0-9_]*]] = getelementptr inbounds{{.*}}[[ACCESSOR_ARRAY2]], i64 0, i64 1
67-
6872
// CHECK load from kernel pointer argument alloca
6973
// CHECK: [[MEM_LOAD2:%[a-zA-Z0-9_]+]] = load i32 addrspace(1)*, i32 addrspace(1)** [[MEM_ARG2]]
7074

71-
// CHECK acc[1] __init method call
72-
// CHECK: [[ACC_CAST2:%[0-9]+]] = addrspacecast %"class{{.*}}accessor"* [[Z1]] to %"class{{.*}}accessor" addrspace(4)*
75+
// CHECK: [[ACC_CAST2:%[0-9]+]] = addrspacecast [[ACCESSOR]]* {{.*}} to [[ACCESSOR]] addrspace(4)*
7376

77+
// CHECK acc[1] __init method call
7478
// CHECK: call spir_func void @{{.*}}__init{{.*}}(%"class.{{.*}}.cl::sycl::accessor" addrspace(4)* [[ACC_CAST2]], i32 addrspace(1)* [[MEM_LOAD2]], %"struct.{{.*}}.cl::sycl::range"* byval({{.*}}) align 4 [[ACC_RANGE2]], %"struct.{{.*}}.cl::sycl::range"* byval({{.*}}) align 4 [[MEM_RANGE2]], %"struct.{{.*}}.cl::sycl::id"* byval({{.*}}) align 4 [[OFFSET2]])

clang/test/SemaSYCL/array-kernel-param-neg.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,12 @@
44
// an array of non-trivially copyable structs as SYCL kernel parameter or
55
// a non-constant size array.
66

7-
struct A {
8-
int i;
9-
};
10-
117
struct B {
128
int i;
139
B(int _i) : i(_i) {}
1410
B(const B &x) : i(x.i) {}
1511
};
1612

17-
struct C : A {
18-
const A C2;
19-
C() : A{0}, C2{2} {}
20-
};
21-
2213
struct D {
2314
int i;
2415
~D();
@@ -38,16 +29,12 @@ __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
3829
}
3930

4031
void test() {
41-
A cs1[10];
4232
B nsl1[4] = {1, 2, 3, 4};
43-
C cs2[6];
4433
D nsl2[5];
4534
E es;
4635
kernel_single_task<class kernel_capture_refs>([=] {
47-
int a = cs1[6].i;
4836
// expected-error@+1 {{kernel parameter has non-trivially copy constructible class/struct type}}
4937
int b = nsl1[2].i;
50-
int c = cs2[0].i;
5138
// expected-error@+1 {{kernel parameter has non-trivially destructible class/struct type}}
5239
int d = nsl2[4].i;
5340
});

clang/test/SemaSYCL/array-kernel-param.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,18 @@ int main() {
5858
// CHECK: FunctionDecl {{.*}}kernel_B{{.*}} 'void (int, int)'
5959
// CHECK-NEXT: ParmVarDecl {{.*}} used _arg_ 'int'
6060
// CHECK-NEXT: ParmVarDecl {{.*}} used _arg_ 'int'
61+
// Check kernel_B inits
62+
// CHECK-NEXT: CompoundStmt
63+
// CHECK-NEXT: DeclStmt
64+
// CHECK-NEXT: VarDecl {{.*}} cinit
65+
// CHECK-NEXT: InitListExpr
66+
// CHECK-NEXT: InitListExpr {{.*}} 'int [2]'
67+
// CHECK: ImplicitCastExpr
68+
// CHECK: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} '_arg_' 'int'
69+
// CHECK: ImplicitCastExpr
70+
// CHECK: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} '_arg_' 'int'
6171

62-
// Correct and enable after struct mebers are extracted into separate parameters
72+
// Correct and enable after struct members are extracted into separate parameters
6373
// C HECK kernel_C parameters
6474
// C HECK: FunctionDecl {{.*}}kernel_C{{.*}} 'void (struct {{.*}}, __global int *, cl::sycl::range<1>, cl::sycl::range<1>, cl::sycl::id<1>, __global int *, cl::sycl::range<1>, cl::sycl::range<1>, cl::sycl::id<1>, __global int *, cl::sycl::range<1>, cl::sycl::range<1>, cl::sycl::id<1>, __global int *, cl::sycl::range<1>, cl::sycl::range<1>, cl::sycl::id<1>)'
6575
// C HECK-NEXT: ParmVarDecl {{.*}} 'struct {{.*}}'

0 commit comments

Comments
 (0)