r262578 - [OPENMP 4.5] Initial support for data members in 'linear' clause.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 2 19:52:24 PST 2016


Author: abataev
Date: Wed Mar  2 21:52:24 2016
New Revision: 262578

URL: http://llvm.org/viewvc/llvm-project?rev=262578&view=rev
Log:
[OPENMP 4.5] Initial support for data members in 'linear' clause.

OpenMP 4.5 allows to privatize data members of current class in member
functions. Patch adds initial support for privatization of data members
in 'linear' clause, no codegen support.

Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/for_ast_print.cpp
    cfe/trunk/test/OpenMP/for_linear_messages.cpp
    cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp
    cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Mar  2 21:52:24 2016
@@ -2185,6 +2185,13 @@ def OMPThreadPrivateDecl : InheritableAt
   let Documentation = [Undocumented];
 }
 
+def OMPCaptureNoInit : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [Undocumented];
+}
+
 def InternalLinkage : InheritableAttr {
   let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
   let Subjects = SubjectList<[Var, Function, CXXRecord]>;

Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Wed Mar  2 21:52:24 2016
@@ -18,6 +18,7 @@
 #include "TargetInfo.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/DeclOpenMP.h"
 using namespace clang;
 using namespace CodeGen;
 
@@ -30,8 +31,15 @@ class OMPLexicalScope {
     for (const auto *C : S.clauses()) {
       if (auto *CPI = OMPClauseWithPreInit::get(C)) {
         if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
-          for (const auto *I : PreInit->decls())
-            CGF.EmitVarDecl(cast<VarDecl>(*I));
+          for (const auto *I : PreInit->decls()) {
+            if (!I->hasAttr<OMPCaptureNoInitAttr>())
+              CGF.EmitVarDecl(cast<VarDecl>(*I));
+            else {
+              CodeGenFunction::AutoVarEmission Emission =
+                  CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
+              CGF.EmitAutoVarCleanups(Emission);
+            }
+          }
         }
       }
     }

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Mar  2 21:52:24 2016
@@ -1706,6 +1706,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMP
 
 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
                                              Expr *CaptureExpr, bool WithInit) {
+  assert(CaptureExpr);
   ASTContext &C = S.getASTContext();
   Expr *Init = CaptureExpr->IgnoreImpCasts();
   QualType Ty = Init->getType();
@@ -1723,12 +1724,11 @@ static OMPCapturedExprDecl *buildCapture
     WithInit = true;
   }
   auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty);
+  if (!WithInit)
+    CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange()));
   S.CurContext->addHiddenDecl(CED);
-  if (WithInit)
-    S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
-                           /*TypeMayContainAuto=*/true);
-  else
-    S.ActOnUninitializedDecl(CED, /*TypeMayContainAuto=*/true);
+  S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
+                         /*TypeMayContainAuto=*/true);
   return CED;
 }
 
@@ -7676,7 +7676,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
       }
       if (TopDVar.CKind == OMPC_firstprivate ||
           (!IsOpenMPCapturedDecl(D) &&
-           !cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit())) {
+           Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
         ExprResult RefRes = DefaultLvalueConversion(Ref);
         if (!RefRes.isUsable())
           continue;
@@ -8277,7 +8277,7 @@ OMPClause *Sema::ActOnOpenMPReductionCla
             buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
         if (!IsOpenMPCapturedDecl(D)) {
           ExprCaptures.push_back(Ref->getDecl());
-          if (!cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit()) {
+          if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
             ExprResult RefRes = DefaultLvalueConversion(Ref);
             if (!RefRes.isUsable())
               continue;
@@ -8340,115 +8340,96 @@ OMPClause *Sema::ActOnOpenMPLinearClause
   }
   for (auto &RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP linear clause.");
-    if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+    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);
       Privates.push_back(nullptr);
       Inits.push_back(nullptr);
-      continue;
     }
-
-    // OpenMP [2.14.3.7, linear clause]
-    // A list item that appears in a linear clause is subject to the private
-    // clause semantics described in Section 2.14.3.3 on page 159 except as
-    // noted. In addition, the value of the new list item on each iteration
-    // of the associated loop(s) corresponds to the value of the original
-    // list item before entering the construct plus the logical number of
-    // the iteration times linear-step.
-
-    SourceLocation ELoc = RefExpr->getExprLoc();
-    // OpenMP [2.1, C/C++]
-    //  A list item is a variable name.
-    // OpenMP  [2.14.3.3, Restrictions, p.1]
-    //  A variable that is part of another variable (as an array or
-    //  structure element) cannot appear in a private clause.
-    DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
-    if (!DE || !isa<VarDecl>(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<VarDecl>(DE->getDecl());
+    QualType Type = D->getType();
+    auto *VD = dyn_cast<VarDecl>(D);
 
     // OpenMP [2.14.3.7, linear clause]
     //  A list-item cannot appear in more than one linear clause.
     //  A list-item that appears in a linear clause cannot appear in any
     //  other data-sharing attribute clause.
-    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
     if (DVar.RefExpr) {
       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
                                           << getOpenMPClauseName(OMPC_linear);
-      ReportOriginalDSA(*this, DSAStack, VD, DVar);
-      continue;
-    }
-
-    QualType QType = VD->getType();
-    if (QType->isDependentType() || QType->isInstantiationDependentType()) {
-      // It will be analyzed later.
-      Vars.push_back(DE);
-      Privates.push_back(nullptr);
-      Inits.push_back(nullptr);
+      ReportOriginalDSA(*this, DSAStack, D, DVar);
       continue;
     }
 
     // A variable must not have an incomplete type or a reference type.
-    if (RequireCompleteType(ELoc, QType,
-                            diag::err_omp_linear_incomplete_type)) {
+    if (RequireCompleteType(ELoc, Type,
+                            diag::err_omp_linear_incomplete_type))
       continue;
-    }
     if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
-        !QType->isReferenceType()) {
+        !Type->isReferenceType()) {
       Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
-          << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
+          << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
       continue;
     }
-    QType = QType.getNonReferenceType();
+    Type = Type.getNonReferenceType();
 
     // A list item must not be const-qualified.
-    if (QType.isConstant(Context)) {
+    if (Type.isConstant(Context)) {
       Diag(ELoc, diag::err_omp_const_variable)
           << getOpenMPClauseName(OMPC_linear);
       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;
     }
 
     // A list item must be of integral or pointer type.
-    QType = QType.getUnqualifiedType().getCanonicalType();
-    const Type *Ty = QType.getTypePtrOrNull();
+    Type = Type.getUnqualifiedType().getCanonicalType();
+    const auto *Ty = Type.getTypePtrOrNull();
     if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
                 !Ty->isPointerType())) {
-      Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType;
+      Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
       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;
     }
 
     // Build private copy of original var.
-    auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(),
-                                 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
-    auto *PrivateRef = buildDeclRefExpr(
-        *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc());
+    auto *Private = buildVarDecl(*this, ELoc, Type, D->getName(),
+                                 D->hasAttrs() ? &D->getAttrs() : nullptr);
+    auto *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
     // Build var to save initial value.
-    VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start");
+    VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
     Expr *InitExpr;
+    DeclRefExpr *Ref = nullptr;
+    if (!VD)
+      Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
     if (LinKind == OMPC_LINEAR_uval)
-      InitExpr = VD->getInit();
+      InitExpr = VD ? VD->getInit() : SimpleRefExpr;
     else
-      InitExpr = DE;
+      InitExpr = VD ? SimpleRefExpr : Ref;
     AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
-                         /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
-    auto InitRef = buildDeclRefExpr(
-        *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc());
-    DSAStack->addDSA(VD, DE, OMPC_linear);
-    Vars.push_back(DE);
+                         /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+    auto InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
+
+    DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
+    Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
     Privates.push_back(PrivateRef);
     Inits.push_back(InitRef);
   }

Modified: cfe/trunk/test/OpenMP/for_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_ast_print.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/for_ast_print.cpp Wed Mar  2 21:52:24 2016
@@ -19,16 +19,22 @@ template <typename T>
 class S7 : public T {
 protected:
   T a;
-  S7() : a(0) {}
+  T &b;
+  typename T::type c:12;
+  typename T::type &d;
+  S7() : a(0), b(a), c(0), d(a.a) {}
 
 public:
-  S7(typename T::type v) : a(v) {
+  S7(typename T::type v) : a(v), b(a), c(v), d(a.a) {
 #pragma omp for private(a) private(this->a) private(T::a)
     for (int k = 0; k < a.a; ++k)
       ++this->a.a;
 #pragma omp for lastprivate(a) lastprivate(this->a) lastprivate(T::a)
     for (int k = 0; k < a.a; ++k)
       ++this->a.a;
+#pragma omp for linear(val(c))
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
   }
   S7 &operator=(S7 &s) {
 #pragma omp for private(a) private(this->a)
@@ -37,16 +43,22 @@ public:
 #pragma omp for lastprivate(a) lastprivate(this->a)
     for (int k = 0; k < s.a.a; ++k)
       ++s.a.a;
+#pragma omp for linear(uval(this->b))
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
     return *this;
   }
 };
 
 // CHECK: #pragma omp for private(this->a) private(this->a) private(this->S::a)
 // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S::a)
+// CHECK: #pragma omp for linear(val(this->c))
 // CHECK: #pragma omp for private(this->a) private(this->a) private(T::a)
 // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(T::a)
+// CHECK: #pragma omp for linear(val(this->c))
 // CHECK: #pragma omp for private(this->a) private(this->a)
 // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a)
+// CHECK: #pragma omp for linear(uval(this->b))
 
 class S8 : public S7<S> {
   S8() {}
@@ -59,6 +71,9 @@ public:
 #pragma omp for lastprivate(a) lastprivate(this->a) lastprivate(S7<S>::a)
     for (int k = 0; k < a.a; ++k)
       ++this->a.a;
+#pragma omp for linear(ref(S7<S>::d))
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
   }
   S8 &operator=(S8 &s) {
 #pragma omp for private(a) private(this->a)
@@ -67,14 +82,19 @@ public:
 #pragma omp for lastprivate(a) lastprivate(this->a)
     for (int k = 0; k < s.a.a; ++k)
       ++s.a.a;
+#pragma omp for linear(this->c)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
     return *this;
   }
 };
 
 // CHECK: #pragma omp for private(this->a) private(this->a) private(this->S7<S>::a)
 // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S7<S>::a)
+// CHECK: #pragma omp for linear(ref(this->S7<S>::d))
 // CHECK: #pragma omp for private(this->a) private(this->a)
 // CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a)
+// CHECK: #pragma omp for linear(this->c)
 
 template <class T, int N>
 T tmain(T argc) {

Modified: cfe/trunk/test/OpenMP/for_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_linear_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_linear_messages.cpp Wed Mar  2 21:52:24 2016
@@ -212,7 +212,7 @@ int main(int argc, char **argv) {
   #pragma omp for linear(i) ordered(1) // expected-error {{'linear' clause cannot be specified along with 'ordered' clause with a parameter}}
   for (int k = 0; k < argc; ++k) ++k;
 
-  foomain<int,char>(argc,argv);
+  foomain<int,char>(argc,argv); // expected-note {{n instantiation of function template specialization 'foomain<int, char>' requested here}}
   return 0;
 }
 

Modified: cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_simd_linear_messages.cpp Wed Mar  2 21:52:24 2016
@@ -208,7 +208,7 @@ int main(int argc, char **argv) {
   #pragma omp for simd linear(i)
   for (int k = 0; k < argc; ++k) ++k;
 
-  foomain<int,char>(argc,argv);
+  foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
   return 0;
 }
 

Modified: cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp Wed Mar  2 21:52:24 2016
@@ -263,7 +263,7 @@ int main(int argc, char **argv) {
   for (int k = 0; k < argc; ++k)
     ++k;
 
-  foomain<int, char>(argc, argv);
+  foomain<int, char>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
   return 0;
 }
 

Modified: cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_simd_linear_messages.cpp Wed Mar  2 21:52:24 2016
@@ -208,7 +208,7 @@ int main(int argc, char **argv) {
   #pragma omp parallel for simd linear(i)
   for (int k = 0; k < argc; ++k) ++k;
 
-  foomain<int,char>(argc,argv);
+  foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
   return 0;
 }
 

Modified: cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp?rev=262578&r1=262577&r2=262578&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/target_parallel_for_linear_messages.cpp Wed Mar  2 21:52:24 2016
@@ -263,7 +263,7 @@ int main(int argc, char **argv) {
   for (int k = 0; k < argc; ++k)
     ++k;
 
-  foomain<int, char>(argc, argv);
+  foomain<int, char>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
   return 0;
 }
 




More information about the cfe-commits mailing list