From 0a4ccec7b79316a6830a6dd47bdac46b8b7a281d Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 16 Jun 2020 11:57:11 -0700 Subject: [PATCH 1/3] [SYCL] IVDep: Add support for struct members and pointers 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. --- clang/include/clang/Basic/Attr.td | 18 ++++--- clang/lib/CodeGen/CGExpr.cpp | 11 +++- clang/lib/CodeGen/CGLoopInfo.cpp | 11 +--- clang/lib/Sema/SemaStmtAttr.cpp | 6 +-- .../CodeGenSYCL/intel-fpga-ivdep-array.cpp | 52 ++++++++++++++++++- clang/test/SemaSYCL/intel-fpga-loops.cpp | 17 ++++++ 6 files changed, 94 insertions(+), 21 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 0cbd314a6681e..5a607dbc2396d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1682,11 +1682,15 @@ def SYCLIntelFPGAIVDep : Attr { (getArrayExpr() && getArrayExpr()->isInstantiationDependent()); } - const VarDecl *getArrayDecl() const { - return getArrayExpr() - ? cast(cast(getArrayExpr())->getDecl()) - ->getCanonicalDecl() - : nullptr; + const ValueDecl *getArrayDecl() const { + const Expr* E = getArrayExpr(); + if (!E) return nullptr; + + if (const auto *DRE = dyn_cast(E)) + return cast(DRE->getDecl()->getCanonicalDecl()); + + return cast( + cast(E)->getMemberDecl()->getCanonicalDecl()); } bool isInf() const { @@ -2582,8 +2586,8 @@ def NoDeref : TypeAttr { // intel::reqd_work_group_size spelling. def ReqdWorkGroupSize : InheritableAttr { let Spellings = [GNU<"reqd_work_group_size">, - CXX11<"intel","reqd_work_group_size">, - CXX11<"cl","reqd_work_group_size">]; + CXX11<"intel","reqd_work_group_size">, + CXX11<"cl","reqd_work_group_size">]; let Args = [UnsignedArgument<"XDim">, DefaultUnsignedArgument<"YDim", 1>, DefaultUnsignedArgument<"ZDim", 1>]; let Subjects = SubjectList<[Function], ErrorDiag>; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ffc48b8ec91b8..a529ec2828334 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3783,10 +3783,19 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); auto *Idx = EmitIdxAfterBase(/*Promote*/true); QualType ptrType = E->getBase()->getType(); + + const ValueDecl *PtrDecl = nullptr; + if (const auto *DRE = + dyn_cast(E->getBase()->IgnoreParenCasts())) + PtrDecl = DRE->getDecl(); + else if (const auto *ME = + dyn_cast(E->getBase()->IgnoreParenCasts())) + PtrDecl = ME->getMemberDecl(); + Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, E->getExprLoc(), &ptrType, - E->getBase()); + E->getBase(), "ptridx", PtrDecl); } LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo); diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index 652a33b8b3d1d..da06b613411b7 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -992,16 +992,9 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, !IntelFPGAMaxInterleaving && !IntelFPGASpeculatedIterations) continue; - if (IntelFPGAIVDep) { - const ValueDecl *Array = nullptr; - if (IntelFPGAIVDep->getArrayExpr()) - Array = - cast(cast(IntelFPGAIVDep->getArrayExpr()) - ->getDecl() - ->getCanonicalDecl()); + if (IntelFPGAIVDep) addSYCLIVDepInfo(Header->getContext(), IntelFPGAIVDep->getSafelenValue(), - Array); - } + IntelFPGAIVDep->getArrayDecl()); if (IntelFPGAII) { llvm::APSInt ArgVal(32); diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 76776bdaadbda..993600afe5e6d 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -148,8 +148,8 @@ static IVDepExprResult HandleFPGAIVDepAttrExpr(Sema &S, Expr *E, return IVDepExprResult::SafeLen; } - if (isa(E)) { - if (!cast(E)->getType()->isArrayType()) { + if (isa(E) | isa(E)) { + if (!E->getType()->isArrayType() && !E->getType()->isPointerType()) { S.Diag(E->getExprLoc(), diag::err_ivdep_declrefexpr_arg); return IVDepExprResult::Invalid; } @@ -249,7 +249,7 @@ CheckRedundantSYCLIntelFPGAIVDepAttrs(Sema &S, ArrayRef Attrs) { if (!A->getArrayExpr()) continue; - const VarDecl *ArrayDecl = A->getArrayDecl(); + const ValueDecl *ArrayDecl = A->getArrayDecl(); auto Other = llvm::find_if(SortedAttrs, [ArrayDecl](const SYCLIntelFPGAIVDepAttr *A) { return ArrayDecl == A->getArrayDecl(); diff --git a/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp b/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp index f920c96db1854..c4f5ebf04c751 100644 --- a/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp +++ b/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -fsycl-is-device -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -fsycl -fsycl-is-device -emit-llvm %s -o - | FileCheck %s // Array-specific ivdep - annotate the correspondent GEPs only // @@ -145,6 +145,39 @@ void ivdep_mul_arrays_and_global() { } } +// CHECK: define spir_func void @_Z{{[0-9]+}}ivdep_ptrv() +void ivdep_ptr() { + int * ptr; + // CHECK: %[[PTR:[0-9a-z]+]] = alloca i32 addrspace(4)* + [[intelfpga::ivdep(ptr, 5)]] + for (int i = 0; i != 10; ++i) + ptr[i] = 0; + // CHECK: %[[PTR_LOAD:[0-9a-z]+]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[PTR]] + // CHECK: %{{[0-9a-z]+}} = getelementptr inbounds i32, i32 addrspace(4)* %[[PTR_LOAD]], i64 %{{[0-9a-z]+}}, !llvm.index.group ![[IDX_GROUP_PTR:[0-9]+]] + // CHECK: br label %for.cond, !llvm.loop ![[MD_LOOP_PTR:[0-9]+]] +} + +// CHECK: define spir_func void @_Z{{[0-9]+}}ivdep_structv() +void ivdep_struct() { + struct S { int *ptr; int arr[10]; } s; + // CHECK: %[[STRUCT:[0-9a-z]+]] = alloca %struct.{{.+}}.S + [[intelfpga::ivdep(s.arr, 5)]] + for (int i = 0; i != 10; ++i) + s.arr[i] = 0; + // CHECK: %[[STRUCT_ARR:[0-9a-z]+]] = getelementptr inbounds %struct.{{.+}}.S, %struct.{{.+}}.S* %[[STRUCT]], i32 0, i32 1 + // 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]+]] + // CHECK: br label %for.cond, !llvm.loop ![[MD_LOOP_STRUCT_ARR:[0-9]+]] + + [[intelfpga::ivdep(s.ptr, 5)]] + for (int i = 0; i != 10; ++i) + s.ptr[i] = 0; + // CHECK: %[[STRUCT_PTR:[0-9a-z]+]] = getelementptr inbounds %struct.{{.+}}.S, %struct.{{.+}}.S* %[[STRUCT]], i32 0, i32 0 + // CHECK: %[[LOAD_STRUCT_PTR:[0-9a-z]+]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[STRUCT_PTR]] + // 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]+]] + // CHECK: br label %for.cond{{[0-9]*}}, !llvm.loop ![[MD_LOOP_STRUCT_PTR:[0-9]+]] +} + + template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { kernelFunc(); @@ -159,6 +192,8 @@ int main() { ivdep_array_and_inf_global(); ivdep_array_and_greater_global(); ivdep_mul_arrays_and_global(); + ivdep_ptr(); + ivdep_struct(); }); return 0; } @@ -225,3 +260,18 @@ int main() { // CHECK-DAG: ![[IVDEP_A_MUL_ARR_AND_GLOB]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_A_MUL_ARR_AND_GLOB]], i32 5} // CHECK-DAG: ![[IVDEP_B_MUL_ARR_AND_GLOB]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_B_MUL_ARR_AND_GLOB]], i32 6} // CHECK-DAG: ![[IVDEP_C_MUL_ARR_AND_GLOB]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_C_MUL_ARR_AND_GLOB]]} + +// CHECK-DAG: ![[IDX_GROUP_PTR]] = distinct !{} +// CHECK-DAG: ![[MD_LOOP_PTR]] = distinct !{![[MD_LOOP_PTR]], ![[IVDEP_PTR:[0-9]+]]} +// CHECK-DAG: ![[IVDEP_PTR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_PTR]], i32 5} +// TODO: ERICH: FIGURE OUT THESE VALUES + +// CHECK-DAG: ![[IDX_GROUP_STRUCT_ARR]] = distinct !{} +// CHECK-DAG: ![[MD_LOOP_STRUCT_ARR]] = distinct !{![[MD_LOOP_STRUCT_ARR]], ![[IVDEP_STRUCT_ARR:[0-9]+]]} +// CHECK-DAG: ![[IVDEP_STRUCT_ARR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_STRUCT_ARR]], i32 5} +// TODO: ERICH: FIGURE OUT THESE VALUES + +// CHECK-DAG: ![[IDX_GROUP_STRUCT_PTR]] = distinct !{} +// CHECK-DAG: ![[MD_LOOP_STRUCT_PTR]] = distinct !{![[MD_LOOP_STRUCT_PTR]], ![[IVDEP_STRUCT_PTR:[0-9]+]]} +// CHECK-DAG: ![[IVDEP_STRUCT_PTR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_STRUCT_PTR]], i32 5} +// TODO: ERICH: FIGURE OUT THESE VALUES diff --git a/clang/test/SemaSYCL/intel-fpga-loops.cpp b/clang/test/SemaSYCL/intel-fpga-loops.cpp index 3b74f436f30f1..d32c3cfa4a0c8 100644 --- a/clang/test/SemaSYCL/intel-fpga-loops.cpp +++ b/clang/test/SemaSYCL/intel-fpga-loops.cpp @@ -141,6 +141,23 @@ void goo() { // no diagnostics are expected [[intelfpga::ivdep(2, a)]] for (int i = 0; i != 10; ++i) a[i] = 0; + + int *ptr; + // no diagnostics are expected + [[intelfpga::ivdep(2, ptr)]] for (int i = 0; i != 10; ++i) + ptr[i] = 0; + + struct S { + int arr[10]; + int *ptr; + } s; + + // no diagnostics are expected + [[intelfpga::ivdep(2, s.arr)]] for (int i = 0; i != 10; ++i) + s.arr[i] = 0; + // no diagnostics are expected + [[intelfpga::ivdep(2, s.ptr)]] for (int i = 0; i != 10; ++i) + s.ptr[i] = 0; } // Test for Intel FPGA loop attributes duplication From a19df40085272e00b63f1f6689d76d2a7d023995 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 16 Jun 2020 12:38:21 -0700 Subject: [PATCH 2/3] Clang-format fixes --- .../CodeGenSYCL/intel-fpga-ivdep-array.cpp | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp b/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp index c4f5ebf04c751..5915ab1ac4a3d 100644 --- a/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp +++ b/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp @@ -147,11 +147,10 @@ void ivdep_mul_arrays_and_global() { // CHECK: define spir_func void @_Z{{[0-9]+}}ivdep_ptrv() void ivdep_ptr() { - int * ptr; + int *ptr; // CHECK: %[[PTR:[0-9a-z]+]] = alloca i32 addrspace(4)* - [[intelfpga::ivdep(ptr, 5)]] - for (int i = 0; i != 10; ++i) - ptr[i] = 0; + [[intelfpga::ivdep(ptr, 5)]] for (int i = 0; i != 10; ++i) + ptr[i] = 0; // CHECK: %[[PTR_LOAD:[0-9a-z]+]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[PTR]] // CHECK: %{{[0-9a-z]+}} = getelementptr inbounds i32, i32 addrspace(4)* %[[PTR_LOAD]], i64 %{{[0-9a-z]+}}, !llvm.index.group ![[IDX_GROUP_PTR:[0-9]+]] // CHECK: br label %for.cond, !llvm.loop ![[MD_LOOP_PTR:[0-9]+]] @@ -159,25 +158,25 @@ void ivdep_ptr() { // CHECK: define spir_func void @_Z{{[0-9]+}}ivdep_structv() void ivdep_struct() { - struct S { int *ptr; int arr[10]; } s; + struct S { + int *ptr; + int arr[10]; + } s; // CHECK: %[[STRUCT:[0-9a-z]+]] = alloca %struct.{{.+}}.S - [[intelfpga::ivdep(s.arr, 5)]] - for (int i = 0; i != 10; ++i) - s.arr[i] = 0; + [[intelfpga::ivdep(s.arr, 5)]] for (int i = 0; i != 10; ++i) + s.arr[i] = 0; // CHECK: %[[STRUCT_ARR:[0-9a-z]+]] = getelementptr inbounds %struct.{{.+}}.S, %struct.{{.+}}.S* %[[STRUCT]], i32 0, i32 1 // 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]+]] // CHECK: br label %for.cond, !llvm.loop ![[MD_LOOP_STRUCT_ARR:[0-9]+]] - [[intelfpga::ivdep(s.ptr, 5)]] - for (int i = 0; i != 10; ++i) - s.ptr[i] = 0; + [[intelfpga::ivdep(s.ptr, 5)]] for (int i = 0; i != 10; ++i) + s.ptr[i] = 0; // CHECK: %[[STRUCT_PTR:[0-9a-z]+]] = getelementptr inbounds %struct.{{.+}}.S, %struct.{{.+}}.S* %[[STRUCT]], i32 0, i32 0 // CHECK: %[[LOAD_STRUCT_PTR:[0-9a-z]+]] = load i32 addrspace(4)*, i32 addrspace(4)** %[[STRUCT_PTR]] // 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]+]] // CHECK: br label %for.cond{{[0-9]*}}, !llvm.loop ![[MD_LOOP_STRUCT_PTR:[0-9]+]] } - template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { kernelFunc(); From 032b001d257c859796fa928b83529c1c662d29e1 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 16 Jun 2020 13:13:32 -0700 Subject: [PATCH 3/3] Fix | to ||, remove stale TODOs --- clang/lib/Sema/SemaStmtAttr.cpp | 2 +- clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 993600afe5e6d..c4f33bd8ffd90 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -148,7 +148,7 @@ static IVDepExprResult HandleFPGAIVDepAttrExpr(Sema &S, Expr *E, return IVDepExprResult::SafeLen; } - if (isa(E) | isa(E)) { + if (isa(E) || isa(E)) { if (!E->getType()->isArrayType() && !E->getType()->isPointerType()) { S.Diag(E->getExprLoc(), diag::err_ivdep_declrefexpr_arg); return IVDepExprResult::Invalid; diff --git a/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp b/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp index 5915ab1ac4a3d..707eeff1ea392 100644 --- a/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp +++ b/clang/test/CodeGenSYCL/intel-fpga-ivdep-array.cpp @@ -263,14 +263,11 @@ int main() { // CHECK-DAG: ![[IDX_GROUP_PTR]] = distinct !{} // CHECK-DAG: ![[MD_LOOP_PTR]] = distinct !{![[MD_LOOP_PTR]], ![[IVDEP_PTR:[0-9]+]]} // CHECK-DAG: ![[IVDEP_PTR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_PTR]], i32 5} -// TODO: ERICH: FIGURE OUT THESE VALUES // CHECK-DAG: ![[IDX_GROUP_STRUCT_ARR]] = distinct !{} // CHECK-DAG: ![[MD_LOOP_STRUCT_ARR]] = distinct !{![[MD_LOOP_STRUCT_ARR]], ![[IVDEP_STRUCT_ARR:[0-9]+]]} // CHECK-DAG: ![[IVDEP_STRUCT_ARR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_STRUCT_ARR]], i32 5} -// TODO: ERICH: FIGURE OUT THESE VALUES // CHECK-DAG: ![[IDX_GROUP_STRUCT_PTR]] = distinct !{} // CHECK-DAG: ![[MD_LOOP_STRUCT_PTR]] = distinct !{![[MD_LOOP_STRUCT_PTR]], ![[IVDEP_STRUCT_PTR:[0-9]+]]} // CHECK-DAG: ![[IVDEP_STRUCT_PTR]] = !{!"llvm.loop.parallel_access_indices", ![[IDX_GROUP_STRUCT_PTR]], i32 5} -// TODO: ERICH: FIGURE OUT THESE VALUES