From 1efd166af693349463a520257d4a536f10dddc9e Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 29 Mar 2016 10:59:56 +0000 Subject: [PATCH] [OPENMP 4.5] Allow data members in 'aligned' clause. OpenMP 4.5 allows privatization of data members OpenMP clauses. Patch adds support for data members in 'aligned' clause. llvm-svn: 264715 --- clang/lib/Sema/SemaOpenMP.cpp | 52 ++++++++-------- clang/test/OpenMP/for_simd_aligned_messages.cpp | 1 + .../OpenMP/parallel_for_simd_aligned_messages.cpp | 1 + clang/test/OpenMP/simd_aligned_messages.cpp | 1 + clang/test/OpenMP/simd_ast_print.cpp | 52 ++++++++++++++++ clang/test/OpenMP/simd_codegen.cpp | 69 +++++++++++++++++++++- .../test/OpenMP/taskloop_simd_aligned_messages.cpp | 1 + 7 files changed, 150 insertions(+), 27 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index c1233d8..8ce67c8 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1745,7 +1745,7 @@ static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit, /*AsExpression=*/false); return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), - SourceLocation()); + CaptureExpr->getExprLoc()); } static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) { @@ -7727,10 +7727,10 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef VarList, } DeclRefExpr *Ref = nullptr; - if (!VD) + if (!VD && IsOpenMPCapturedDecl(D)) Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true); DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref); - Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref); + Vars.push_back((VD || !Ref) ? RefExpr->IgnoreParens() : Ref); } if (Vars.empty()) @@ -8692,53 +8692,55 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( SmallVector Vars; for (auto &RefExpr : VarList) { - assert(RefExpr && "NULL expr in OpenMP aligned clause."); - if (isa(RefExpr)) { + assert(RefExpr && "NULL expr in OpenMP linear clause."); + SourceLocation ELoc; + SourceRange ERange; + Expr *SimpleRefExpr = RefExpr; + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, + /*AllowArraySection=*/false); + if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); - continue; } - - SourceLocation ELoc = RefExpr->getExprLoc(); - // OpenMP [2.1, C/C++] - // A list item is a variable name. - DeclRefExpr *DE = dyn_cast(RefExpr); - if (!DE || !isa(DE->getDecl())) { - Diag(ELoc, diag::err_omp_expected_var_name_member_expr) - << 0 << RefExpr->getSourceRange(); + ValueDecl *D = Res.first; + if (!D) continue; - } - VarDecl *VD = cast(DE->getDecl()); + QualType QType = D->getType(); + auto *VD = dyn_cast(D); // OpenMP [2.8.1, simd construct, Restrictions] // The type of list items appearing in the aligned clause must be // array, pointer, reference to array, or reference to pointer. - QualType QType = VD->getType(); QType = QType.getNonReferenceType().getUnqualifiedType().getCanonicalType(); const Type *Ty = QType.getTypePtrOrNull(); - if (!Ty || (!Ty->isDependentType() && !Ty->isArrayType() && - !Ty->isPointerType())) { + if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) { Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr) - << QType << getLangOpts().CPlusPlus << RefExpr->getSourceRange(); + << QType << getLangOpts().CPlusPlus << ERange; bool IsDecl = + !VD || VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; - Diag(VD->getLocation(), + Diag(D->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; + << D; continue; } // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. - if (Expr *PrevRef = DSAStack->addUniqueAligned(VD, DE)) { - Diag(ELoc, diag::err_omp_aligned_twice) << RefExpr->getSourceRange(); + if (Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) { + Diag(ELoc, diag::err_omp_aligned_twice) << ERange; Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); continue; } - Vars.push_back(DE); + DeclRefExpr *Ref = nullptr; + if (!VD && IsOpenMPCapturedDecl(D)) + Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true); + Vars.push_back(DefaultFunctionArrayConversion( + (VD || !Ref) ? RefExpr->IgnoreParens() : Ref) + .get()); } // OpenMP [2.8.1, simd construct, Description] diff --git a/clang/test/OpenMP/for_simd_aligned_messages.cpp b/clang/test/OpenMP/for_simd_aligned_messages.cpp index 1007b3c..cef83c3 100644 --- a/clang/test/OpenMP/for_simd_aligned_messages.cpp +++ b/clang/test/OpenMP/for_simd_aligned_messages.cpp @@ -196,6 +196,7 @@ int main(int argc, char **argv) { #pragma omp for simd aligned(h) for (int k = 0; k < argc; ++k) ++k; int *pargc = &argc; + // expected-note@+1 {{in instantiation of function template specialization 'foomain' requested here}} foomain(pargc,argv); return 0; } diff --git a/clang/test/OpenMP/parallel_for_simd_aligned_messages.cpp b/clang/test/OpenMP/parallel_for_simd_aligned_messages.cpp index 8bffd21..2ccdf06 100644 --- a/clang/test/OpenMP/parallel_for_simd_aligned_messages.cpp +++ b/clang/test/OpenMP/parallel_for_simd_aligned_messages.cpp @@ -196,6 +196,7 @@ int main(int argc, char **argv) { #pragma omp parallel for simd aligned(h) for (int k = 0; k < argc; ++k) ++k; int *pargc = &argc; + // expected-note@+1 {{in instantiation of function template specialization 'foomain' requested here}} foomain(pargc,argv); return 0; } diff --git a/clang/test/OpenMP/simd_aligned_messages.cpp b/clang/test/OpenMP/simd_aligned_messages.cpp index 6be7529..9515a0b 100644 --- a/clang/test/OpenMP/simd_aligned_messages.cpp +++ b/clang/test/OpenMP/simd_aligned_messages.cpp @@ -196,6 +196,7 @@ int main(int argc, char **argv) { #pragma omp simd aligned(h) for (int k = 0; k < argc; ++k) ++k; int *pargc = &argc; + // expected-note@+1 {{in instantiation of function template specialization 'foomain' requested here}} foomain(pargc,argv); return 0; } diff --git a/clang/test/OpenMP/simd_ast_print.cpp b/clang/test/OpenMP/simd_ast_print.cpp index cabbe33..99c00c6 100644 --- a/clang/test/OpenMP/simd_ast_print.cpp +++ b/clang/test/OpenMP/simd_ast_print.cpp @@ -6,6 +6,58 @@ #ifndef HEADER #define HEADER +struct SS { + SS(): a(0) {} + SS(int v) : a(v) {} + int a; + typedef int type; +}; + +template +class S7 : public T { +protected: + T *a; + T b[2]; + S7() : a(0) {} + +public: + S7(typename T::type &v) : a((T*)&v) { +#pragma omp simd aligned(a) + for (int k = 0; k < a->a; ++k) + ++this->a->a; + } + S7 &operator=(S7 &s) { +#pragma omp simd aligned(this->b : 8) + for (int k = 0; k < s.a->a; ++k) + ++s.a->a; + return *this; + } +}; + +// CHECK: #pragma omp simd aligned(this->a) +// CHECK: #pragma omp simd aligned(this->a) +// CHECK: #pragma omp simd aligned(this->b: 8) + +class S8 : public S7 { + S8() {} + +public: + S8(int v) : S7(v){ +#pragma omp simd aligned(S7::a) + for (int k = 0; k < a->a; ++k) + ++this->a->a; + } + S8 &operator=(S8 &s) { +#pragma omp simd aligned(this->b: 4) + for (int k = 0; k < s.a->a; ++k) + ++s.a->a; + return *this; + } +}; + +// CHECK: #pragma omp simd aligned(this->S7::a) +// CHECK: #pragma omp simd aligned(this->b: 4) + void foo() {} int g_ind = 1; template T reduct(T* arr, N num) { diff --git a/clang/test/OpenMP/simd_codegen.cpp b/clang/test/OpenMP/simd_codegen.cpp index 6d78766..a43d999 100644 --- a/clang/test/OpenMP/simd_codegen.cpp +++ b/clang/test/OpenMP/simd_codegen.cpp @@ -4,8 +4,10 @@ // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG // REQUIRES: x86-registered-target // expected-no-diagnostics -#ifndef HEADER -#define HEADER + #ifndef HEADER + #define HEADER + +// CHECK: [[SS_TY:%.+]] = type { i32 } long long get_val() { return 0; } double *g_ptr; @@ -632,5 +634,68 @@ void parallel_simd(float *a) { a[i] += bar(); } // TERM_DEBUG: !{{[0-9]+}} = !DILocation(line: [[@LINE-11]], + +// CHECK-LABEL: S8 +// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64 +// CHECK-NEXT: and i64 %{{.+}}, 15 +// CHECK-NEXT: icmp eq i64 %{{.+}}, 0 +// CHECK-NEXT: call void @llvm.assume(i1 + +// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64 +// CHECK-NEXT: and i64 %{{.+}}, 7 +// CHECK-NEXT: icmp eq i64 %{{.+}}, 0 +// CHECK-NEXT: call void @llvm.assume(i1 + +// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64 +// CHECK-NEXT: and i64 %{{.+}}, 15 +// CHECK-NEXT: icmp eq i64 %{{.+}}, 0 +// CHECK-NEXT: call void @llvm.assume(i1 + +// CHECK: ptrtoint [[SS_TY]]* %{{.+}} to i64 +// CHECK-NEXT: and i64 %{{.+}}, 3 +// CHECK-NEXT: icmp eq i64 %{{.+}}, 0 +// CHECK-NEXT: call void @llvm.assume(i1 +struct SS { + SS(): a(0) {} + SS(int v) : a(v) {} + int a; + typedef int type; +}; + +template +class S7 : public T { +protected: + T *a; + T b[2]; + S7() : a(0) {} + +public: + S7(typename T::type &v) : a((T*)&v) { +#pragma omp simd aligned(a) + for (int k = 0; k < a->a; ++k) + ++this->a->a; +#pragma omp simd aligned(this->b : 8) + for (int k = 0; k < a->a; ++k) + ++a->a; + } +}; + +class S8 : private IterDouble, public S7 { + S8() {} + +public: + S8(int v) : S7(v){ +#pragma omp parallel private(a) +#pragma omp simd aligned(S7::a) + for (int k = 0; k < a->a; ++k) + ++this->a->a; +#pragma omp parallel shared(b) +#pragma omp simd aligned(this->b: 4) + for (int k = 0; k < a->a; ++k) + ++a->a; + } +}; +S8 s8(0); + #endif // HEADER diff --git a/clang/test/OpenMP/taskloop_simd_aligned_messages.cpp b/clang/test/OpenMP/taskloop_simd_aligned_messages.cpp index b62af04..b45f44f 100644 --- a/clang/test/OpenMP/taskloop_simd_aligned_messages.cpp +++ b/clang/test/OpenMP/taskloop_simd_aligned_messages.cpp @@ -196,6 +196,7 @@ int main(int argc, char **argv) { #pragma omp taskloop simd aligned(h) for (int k = 0; k < argc; ++k) ++k; int *pargc = &argc; + // expected-note@+1 {{in instantiation of function template specialization 'foomain' requested here}} foomain(pargc,argv); return 0; } -- 2.7.4