Skip to content

Commit 358ec04

Browse files
author
Erich Keane
authored
[SYCL] IVDep: Add support for struct members and pointers (#1908)
Struct members was missed in the initial implementation, we just need to properly handle the MemberExpr when doing our SEMA (+ consider it in a few other places). Pointers should be allowed, since the arrays decay to pointer pretty easily in the type system. The implementation is as simple as allowing it in Sema, then making sure we pass the Decl to the GEP creation function.
1 parent ebefb26 commit 358ec04

File tree

6 files changed

+90
-21
lines changed

6 files changed

+90
-21
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,11 +1682,15 @@ def SYCLIntelFPGAIVDep : Attr {
16821682
(getArrayExpr() && getArrayExpr()->isInstantiationDependent());
16831683
}
16841684

1685-
const VarDecl *getArrayDecl() const {
1686-
return getArrayExpr()
1687-
? cast<VarDecl>(cast<DeclRefExpr>(getArrayExpr())->getDecl())
1688-
->getCanonicalDecl()
1689-
: nullptr;
1685+
const ValueDecl *getArrayDecl() const {
1686+
const Expr* E = getArrayExpr();
1687+
if (!E) return nullptr;
1688+
1689+
if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
1690+
return cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
1691+
1692+
return cast<ValueDecl>(
1693+
cast<MemberExpr>(E)->getMemberDecl()->getCanonicalDecl());
16901694
}
16911695

16921696
bool isInf() const {
@@ -2582,8 +2586,8 @@ def NoDeref : TypeAttr {
25822586
// intel::reqd_work_group_size spelling.
25832587
def ReqdWorkGroupSize : InheritableAttr {
25842588
let Spellings = [GNU<"reqd_work_group_size">,
2585-
CXX11<"intel","reqd_work_group_size">,
2586-
CXX11<"cl","reqd_work_group_size">];
2589+
CXX11<"intel","reqd_work_group_size">,
2590+
CXX11<"cl","reqd_work_group_size">];
25872591
let Args = [UnsignedArgument<"XDim">, DefaultUnsignedArgument<"YDim", 1>,
25882592
DefaultUnsignedArgument<"ZDim", 1>];
25892593
let Subjects = SubjectList<[Function], ErrorDiag>;

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3782,10 +3782,19 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
37823782
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
37833783
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
37843784
QualType ptrType = E->getBase()->getType();
3785+
3786+
const ValueDecl *PtrDecl = nullptr;
3787+
if (const auto *DRE =
3788+
dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenCasts()))
3789+
PtrDecl = DRE->getDecl();
3790+
else if (const auto *ME =
3791+
dyn_cast<MemberExpr>(E->getBase()->IgnoreParenCasts()))
3792+
PtrDecl = ME->getMemberDecl();
3793+
37853794
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
37863795
!getLangOpts().isSignedOverflowDefined(),
37873796
SignedIndices, E->getExprLoc(), &ptrType,
3788-
E->getBase());
3797+
E->getBase(), "ptridx", PtrDecl);
37893798
}
37903799

37913800
LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);

clang/lib/CodeGen/CGLoopInfo.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -992,16 +992,9 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
992992
!IntelFPGAMaxInterleaving && !IntelFPGASpeculatedIterations)
993993
continue;
994994

995-
if (IntelFPGAIVDep) {
996-
const ValueDecl *Array = nullptr;
997-
if (IntelFPGAIVDep->getArrayExpr())
998-
Array =
999-
cast<ValueDecl>(cast<DeclRefExpr>(IntelFPGAIVDep->getArrayExpr())
1000-
->getDecl()
1001-
->getCanonicalDecl());
995+
if (IntelFPGAIVDep)
1002996
addSYCLIVDepInfo(Header->getContext(), IntelFPGAIVDep->getSafelenValue(),
1003-
Array);
1004-
}
997+
IntelFPGAIVDep->getArrayDecl());
1005998

1006999
if (IntelFPGAII) {
10071000
llvm::APSInt ArgVal(32);

clang/lib/Sema/SemaStmtAttr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ static IVDepExprResult HandleFPGAIVDepAttrExpr(Sema &S, Expr *E,
148148
return IVDepExprResult::SafeLen;
149149
}
150150

151-
if (isa<DeclRefExpr>(E)) {
152-
if (!cast<DeclRefExpr>(E)->getType()->isArrayType()) {
151+
if (isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) {
152+
if (!E->getType()->isArrayType() && !E->getType()->isPointerType()) {
153153
S.Diag(E->getExprLoc(), diag::err_ivdep_declrefexpr_arg);
154154
return IVDepExprResult::Invalid;
155155
}
@@ -249,7 +249,7 @@ CheckRedundantSYCLIntelFPGAIVDepAttrs(Sema &S, ArrayRef<const Attr *> Attrs) {
249249
if (!A->getArrayExpr())
250250
continue;
251251

252-
const VarDecl *ArrayDecl = A->getArrayDecl();
252+
const ValueDecl *ArrayDecl = A->getArrayDecl();
253253
auto Other = llvm::find_if(SortedAttrs,
254254
[ArrayDecl](const SYCLIntelFPGAIVDepAttr *A) {
255255
return ArrayDecl == A->getArrayDecl();

clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -fsycl-is-device -emit-llvm %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -fsycl -fsycl-is-device -emit-llvm %s -o - | FileCheck %s
22

33
// Array-specific ivdep - annotate the correspondent GEPs only
44
//
@@ -145,6 +145,38 @@ void ivdep_mul_arrays_and_global() {
145145
}
146146
}
147147

148+
// CHECK: define spir_func void @_Z{{[0-9]+}}ivdep_ptrv()
149+
void ivdep_ptr() {
150+
int *ptr;
151+
// CHECK: %[[PTR:[0-9a-z]+]] = alloca i32 addrspace(4)*
152+
[[intelfpga::ivdep(ptr, 5)]] for (int i = 0; i != 10; ++i)
153+
ptr[i] = 0;
154+
// CHECK: %[[PTR_LOAD:[0-9a-z]+]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[PTR]]
155+
// CHECK: %{{[0-9a-z]+}} = getelementptr inbounds i32, i32 addrspace(4)* %[[PTR_LOAD]], i64 %{{[0-9a-z]+}}, !llvm.index.group ![[IDX_GROUP_PTR:[0-9]+]]
156+
// CHECK: br label %for.cond, !llvm.loop ![[MD_LOOP_PTR:[0-9]+]]
157+
}
158+
159+
// CHECK: define spir_func void @_Z{{[0-9]+}}ivdep_structv()
160+
void ivdep_struct() {
161+
struct S {
162+
int *ptr;
163+
int arr[10];
164+
} s;
165+
// CHECK: %[[STRUCT:[0-9a-z]+]] = alloca %struct.{{.+}}.S
166+
[[intelfpga::ivdep(s.arr, 5)]] for (int i = 0; i != 10; ++i)
167+
s.arr[i] = 0;
168+
// CHECK: %[[STRUCT_ARR:[0-9a-z]+]] = getelementptr inbounds %struct.{{.+}}.S, %struct.{{.+}}.S* %[[STRUCT]], i32 0, i32 1
169+
// CHECK: %{{[0-9a-z]+}} = getelementptr inbounds [10 x i32], [10 x i32]* %[[STRUCT_ARR]], i64 0, i64 %{{[0-9a-z]+}}, !llvm.index.group ![[IDX_GROUP_STRUCT_ARR:[0-9]+]]
170+
// CHECK: br label %for.cond, !llvm.loop ![[MD_LOOP_STRUCT_ARR:[0-9]+]]
171+
172+
[[intelfpga::ivdep(s.ptr, 5)]] for (int i = 0; i != 10; ++i)
173+
s.ptr[i] = 0;
174+
// CHECK: %[[STRUCT_PTR:[0-9a-z]+]] = getelementptr inbounds %struct.{{.+}}.S, %struct.{{.+}}.S* %[[STRUCT]], i32 0, i32 0
175+
// CHECK: %[[LOAD_STRUCT_PTR:[0-9a-z]+]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[STRUCT_PTR]]
176+
// CHECK: %{{[0-9a-z]+}} = getelementptr inbounds i32, i32 addrspace(4)* %[[LOAD_STRUCT_PTR]], i64 %{{[0-9a-z]+}}, !llvm.index.group ![[IDX_GROUP_STRUCT_PTR:[0-9]+]]
177+
// CHECK: br label %for.cond{{[0-9]*}}, !llvm.loop ![[MD_LOOP_STRUCT_PTR:[0-9]+]]
178+
}
179+
148180
template <typename name, typename Func>
149181
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
150182
kernelFunc();
@@ -159,6 +191,8 @@ int main() {
159191
ivdep_array_and_inf_global();
160192
ivdep_array_and_greater_global();
161193
ivdep_mul_arrays_and_global();
194+
ivdep_ptr();
195+
ivdep_struct();
162196
});
163197
return 0;
164198
}
@@ -225,3 +259,15 @@ int main() {
225259
// CHECK-DAG: ![[IVDEP_A_MUL_ARR_AND_GLOB]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_A_MUL_ARR_AND_GLOB]], i32 5}
226260
// CHECK-DAG: ![[IVDEP_B_MUL_ARR_AND_GLOB]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_B_MUL_ARR_AND_GLOB]], i32 6}
227261
// CHECK-DAG: ![[IVDEP_C_MUL_ARR_AND_GLOB]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_C_MUL_ARR_AND_GLOB]]}
262+
263+
// CHECK-DAG: ![[IDX_GROUP_PTR]] = distinct !{}
264+
// CHECK-DAG: ![[MD_LOOP_PTR]] = distinct !{![[MD_LOOP_PTR]], ![[IVDEP_PTR:[0-9]+]]}
265+
// CHECK-DAG: ![[IVDEP_PTR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_PTR]], i32 5}
266+
267+
// CHECK-DAG: ![[IDX_GROUP_STRUCT_ARR]] = distinct !{}
268+
// CHECK-DAG: ![[MD_LOOP_STRUCT_ARR]] = distinct !{![[MD_LOOP_STRUCT_ARR]], ![[IVDEP_STRUCT_ARR:[0-9]+]]}
269+
// CHECK-DAG: ![[IVDEP_STRUCT_ARR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_STRUCT_ARR]], i32 5}
270+
271+
// CHECK-DAG: ![[IDX_GROUP_STRUCT_PTR]] = distinct !{}
272+
// CHECK-DAG: ![[MD_LOOP_STRUCT_PTR]] = distinct !{![[MD_LOOP_STRUCT_PTR]], ![[IVDEP_STRUCT_PTR:[0-9]+]]}
273+
// CHECK-DAG: ![[IVDEP_STRUCT_PTR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_STRUCT_PTR]], i32 5}

clang/test/SemaSYCL/intel-fpga-loops.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,23 @@ void goo() {
141141
// no diagnostics are expected
142142
[[intelfpga::ivdep(2, a)]] for (int i = 0; i != 10; ++i)
143143
a[i] = 0;
144+
145+
int *ptr;
146+
// no diagnostics are expected
147+
[[intelfpga::ivdep(2, ptr)]] for (int i = 0; i != 10; ++i)
148+
ptr[i] = 0;
149+
150+
struct S {
151+
int arr[10];
152+
int *ptr;
153+
} s;
154+
155+
// no diagnostics are expected
156+
[[intelfpga::ivdep(2, s.arr)]] for (int i = 0; i != 10; ++i)
157+
s.arr[i] = 0;
158+
// no diagnostics are expected
159+
[[intelfpga::ivdep(2, s.ptr)]] for (int i = 0; i != 10; ++i)
160+
s.ptr[i] = 0;
144161
}
145162

146163
// Test for Intel FPGA loop attributes duplication

0 commit comments

Comments
 (0)