r266052 - [OPENMP 4.0] Support for 'aligned' clause in 'declare simd' directive.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 12 02:35:56 PDT 2016


Author: abataev
Date: Tue Apr 12 04:35:56 2016
New Revision: 266052

URL: http://llvm.org/viewvc/llvm-project?rev=266052&view=rev
Log:
[OPENMP 4.0] Support for 'aligned' clause in 'declare simd' directive.

The aligned clause declares that the object to which each list item points is aligned to the number of bytes expressed in the optional parameter of the aligned clause.
'aligned' '(' <argument-list> [ ':' <alignment> ] ')'
The optional parameter of the aligned clause, alignment, must be a constant positive integer expression. If no optional parameter is specified, implementation-defined default alignments for SIMD instructions on the target platforms are assumed.
The special this pointer can be used as if was one of the arguments to the function in any of the linear, aligned, or uniform clauses.

Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseOpenMP.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/OpenMP/declare_simd_ast_print.c
    cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp
    cfe/trunk/test/OpenMP/declare_simd_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=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Apr 12 04:35:56 2016
@@ -2276,7 +2276,8 @@ def OMPDeclareSimdDecl : Attr {
     EnumArgument<"BranchState", "BranchStateTy",
                  [ "", "inbranch", "notinbranch" ],
                  [ "BS_Undefined", "BS_Inbranch", "BS_Notinbranch" ]>,
-    ExprArgument<"Simdlen">, VariadicExprArgument<"Uniforms">
+    ExprArgument<"Simdlen">, VariadicExprArgument<"Uniforms">,
+    VariadicExprArgument<"Aligneds">, VariadicExprArgument<"Alignments">
   ];
   let AdditionalMembers = [{
     void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
@@ -2298,6 +2299,17 @@ def OMPDeclareSimdDecl : Attr {
         }
         OS << ") ";
       }
+      alignments_iterator NI = alignments_begin();
+      for (auto E : aligneds()) {
+        OS << "aligned(";
+        E->printPretty(OS, nullptr, Policy);
+        if (*NI) {
+          OS << ": ";
+          (*NI)->printPretty(OS, nullptr, Policy);
+        }
+        OS << ") ";
+        ++NI;
+      }
     }
   }];
 }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 12 04:35:56 2016
@@ -7950,7 +7950,7 @@ def err_omp_aligned_expected_array_or_pt
   "%select{ or pointer|, pointer, reference to array or reference to pointer}1"
   ", not %0">;
 def err_omp_aligned_twice : Error<
-  "a variable cannot appear in more than one aligned clause">;
+  "%select{a variable|a parameter|'this'}0 cannot appear in more than one aligned clause">;
 def err_omp_local_var_in_threadprivate_init : Error<
   "variable with local storage in initial value of threadprivate variable">;
 def err_omp_loop_not_canonical_init : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 12 04:35:56 2016
@@ -8112,7 +8112,8 @@ public:
   /// the associated method/function.
   DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(
       DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS,
-      Expr *Simdlen, ArrayRef<Expr *> Uniforms, SourceRange SR);
+      Expr *Simdlen, ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
+      ArrayRef<Expr *> Alignments, SourceRange SR);
 
   OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                          Expr *Expr,

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Tue Apr 12 04:35:56 2016
@@ -329,63 +329,6 @@ Parser::ParseOpenMPDeclareReductionDirec
                                                          IsCorrect);
 }
 
-/// Parses clauses for 'declare simd' directive.
-///    clause:
-///      'inbranch' | 'notinbranch'
-///      'simdlen' '(' <expr> ')'
-///      { 'uniform' '(' <argument_list> ')' }
-static bool parseDeclareSimdClauses(Parser &P,
-                                    OMPDeclareSimdDeclAttr::BranchStateTy &BS,
-                                    ExprResult &SimdLen,
-                                    SmallVectorImpl<Expr *> &Uniforms) {
-  SourceRange BSRange;
-  const Token &Tok = P.getCurToken();
-  bool IsError = false;
-  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
-    if (Tok.isNot(tok::identifier))
-      break;
-    OMPDeclareSimdDeclAttr::BranchStateTy Out;
-    IdentifierInfo *II = Tok.getIdentifierInfo();
-    StringRef ClauseName = II->getName();
-    // Parse 'inranch|notinbranch' clauses.
-    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
-      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
-        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
-            << ClauseName
-            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
-        IsError = true;
-      }
-      BS = Out;
-      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
-      P.ConsumeToken();
-    } else if (ClauseName.equals("simdlen")) {
-      if (SimdLen.isUsable()) {
-        P.Diag(Tok, diag::err_omp_more_one_clause)
-            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
-        IsError = true;
-      }
-      P.ConsumeToken();
-      SourceLocation RLoc;
-      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
-      if (SimdLen.isInvalid())
-        IsError = true;
-    } else if (ClauseName.equals("uniform")) {
-      Parser::OpenMPVarListDataTy Data;
-
-      P.ConsumeToken();
-      if (P.ParseOpenMPVarList(OMPD_declare_simd,
-                               getOpenMPClauseKind(ClauseName), Uniforms, Data))
-        IsError = true;
-    } else
-      // TODO: add parsing of other clauses.
-      break;
-    // Skip ',' if any.
-    if (Tok.is(tok::comma))
-      P.ConsumeToken();
-  }
-  return IsError;
-}
-
 namespace {
 /// RAII that recreates function context for correct parsing of clauses of
 /// 'declare simd' construct.
@@ -442,6 +385,75 @@ public:
 };
 } // namespace
 
+/// Parses clauses for 'declare simd' directive.
+///    clause:
+///      'inbranch' | 'notinbranch'
+///      'simdlen' '(' <expr> ')'
+///      { 'uniform' '(' <argument_list> ')' }
+///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
+static bool parseDeclareSimdClauses(Parser &P,
+                                    OMPDeclareSimdDeclAttr::BranchStateTy &BS,
+                                    ExprResult &SimdLen,
+                                    SmallVectorImpl<Expr *> &Uniforms,
+                                    SmallVectorImpl<Expr *> &Aligneds,
+                                    SmallVectorImpl<Expr *> &Alignments) {
+  SourceRange BSRange;
+  const Token &Tok = P.getCurToken();
+  bool IsError = false;
+  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+    if (Tok.isNot(tok::identifier))
+      break;
+    OMPDeclareSimdDeclAttr::BranchStateTy Out;
+    IdentifierInfo *II = Tok.getIdentifierInfo();
+    StringRef ClauseName = II->getName();
+    // Parse 'inranch|notinbranch' clauses.
+    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
+      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
+        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
+            << ClauseName
+            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
+        IsError = true;
+      }
+      BS = Out;
+      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
+      P.ConsumeToken();
+    } else if (ClauseName.equals("simdlen")) {
+      if (SimdLen.isUsable()) {
+        P.Diag(Tok, diag::err_omp_more_one_clause)
+            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
+        IsError = true;
+      }
+      P.ConsumeToken();
+      SourceLocation RLoc;
+      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
+      if (SimdLen.isInvalid())
+        IsError = true;
+    } else {
+      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
+      if (CKind == OMPC_uniform || CKind == OMPC_aligned) {
+        Parser::OpenMPVarListDataTy Data;
+        auto *Vars = &Uniforms;
+        if (CKind == OMPC_aligned) {
+          Vars = &Aligneds;
+        }
+
+        P.ConsumeToken();
+        if (P.ParseOpenMPVarList(OMPD_declare_simd,
+                                 getOpenMPClauseKind(ClauseName), *Vars, Data))
+          IsError = true;
+        if (CKind == OMPC_aligned)
+          Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
+      } else
+        // TODO: add parsing of other clauses.
+        break;
+    }
+    // Skip ',' if any.
+    if (Tok.is(tok::comma))
+      P.ConsumeToken();
+  }
+  return IsError;
+}
+
 /// Parse clauses for '#pragma omp declare simd'.
 Parser::DeclGroupPtrTy
 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
@@ -456,7 +468,10 @@ Parser::ParseOMPDeclareSimdClauses(Parse
       OMPDeclareSimdDeclAttr::BS_Undefined;
   ExprResult Simdlen;
   SmallVector<Expr *, 4> Uniforms;
-  bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms);
+  SmallVector<Expr *, 4> Aligneds;
+  SmallVector<Expr *, 4> Alignments;
+  bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
+                                         Alignments);
   // Need to check for extra tokens.
   if (Tok.isNot(tok::annot_pragma_openmp_end)) {
     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
@@ -466,9 +481,11 @@ Parser::ParseOMPDeclareSimdClauses(Parse
   }
   // Skip the last annot_pragma_openmp_end.
   SourceLocation EndLoc = ConsumeToken();
-  if (!IsError)
+  if (!IsError) {
     return Actions.ActOnOpenMPDeclareSimdDirective(
-        Ptr, BS, Simdlen.get(), Uniforms, SourceRange(Loc, EndLoc));
+        Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments,
+        SourceRange(Loc, EndLoc));
+  }
   return Ptr;
 }
 

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Tue Apr 12 04:35:56 2016
@@ -3192,7 +3192,9 @@ StmtResult Sema::ActOnOpenMPExecutableDi
 
 Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
     DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
-    ArrayRef<Expr *> Uniforms, SourceRange SR) {
+    ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
+    ArrayRef<Expr *> Alignments, SourceRange SR) {
+  assert(Aligneds.size() == Alignments.size());
   if (!DG || DG.get().isNull())
     return DeclGroupPtrTy();
 
@@ -3235,9 +3237,76 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDe
     Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
         << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
   }
+  // OpenMP [2.8.2, declare simd construct, Description]
+  // The aligned clause declares that the object to which each list item points
+  // is aligned to the number of bytes expressed in the optional parameter of
+  // the aligned clause.
+  // The special this pointer can be used as if was one of the arguments to the
+  // function in any of the linear, aligned, or uniform clauses.
+  // The type of list items appearing in the aligned clause must be array,
+  // pointer, reference to array, or reference to pointer.
+  llvm::DenseMap<Decl *, Expr *> AlignedArgs;
+  Expr *AlignedThis = nullptr;
+  for (auto *E : Aligneds) {
+    E = E->IgnoreParenImpCasts();
+    if (auto *DRE = dyn_cast<DeclRefExpr>(E))
+      if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+        auto *CanonPVD = PVD->getCanonicalDecl();
+        if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
+            FD->getParamDecl(PVD->getFunctionScopeIndex())
+                    ->getCanonicalDecl() == CanonPVD) {
+          // OpenMP  [2.8.1, simd construct, Restrictions]
+          // A list-item cannot appear in more than one aligned clause.
+          if (AlignedArgs.count(CanonPVD) > 0) {
+            Diag(E->getExprLoc(), diag::err_omp_aligned_twice)
+                << 1 << E->getSourceRange();
+            Diag(AlignedArgs[CanonPVD]->getExprLoc(),
+                 diag::note_omp_explicit_dsa)
+                << getOpenMPClauseName(OMPC_aligned);
+            continue;
+          }
+          AlignedArgs[CanonPVD] = E;
+          QualType QTy = PVD->getType()
+                             .getNonReferenceType()
+                             .getUnqualifiedType()
+                             .getCanonicalType();
+          const Type *Ty = QTy.getTypePtrOrNull();
+          if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
+            Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
+                << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
+            Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
+          }
+          continue;
+        }
+      }
+    if (isa<CXXThisExpr>(E)) {
+      if (AlignedThis) {
+        Diag(E->getExprLoc(), diag::err_omp_aligned_twice)
+            << 2 << E->getSourceRange();
+        Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
+            << getOpenMPClauseName(OMPC_aligned);
+      }
+      AlignedThis = E;
+      continue;
+    }
+    Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
+        << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
+  }
+  // The optional parameter of the aligned clause, alignment, must be a constant
+  // positive integer expression. If no optional parameter is specified,
+  // implementation-defined default alignments for SIMD instructions on the
+  // target platforms are assumed.
+  SmallVector<Expr *, 4> NewAligns;
+  for (auto *E : Alignments) {
+    ExprResult Align;
+    if (E)
+      Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
+    NewAligns.push_back(Align.get());
+  }
   auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
       Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
-      Uniforms.size(), SR);
+      Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
+      const_cast<Expr **>(NewAligns.data()), NewAligns.size(), SR);
   ADecl->addAttr(NewAttr);
   return ConvertDeclToDeclGroup(ADecl);
 }
@@ -8859,7 +8928,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClaus
     // OpenMP  [2.8.1, simd construct, Restrictions]
     // A list-item cannot appear in more than one aligned clause.
     if (Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
-      Diag(ELoc, diag::err_omp_aligned_twice) << ERange;
+      Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange;
       Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
           << getOpenMPClauseName(OMPC_aligned);
       continue;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Apr 12 04:35:56 2016
@@ -247,7 +247,7 @@ static void instantiateOMPDeclareSimdDec
     New = FTD->getTemplatedDecl();
   auto *FD = cast<FunctionDecl>(New);
   auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(FD->getDeclContext());
-  SmallVector<Expr *, 4> Uniforms;
+  SmallVector<Expr *, 4> Uniforms, Aligneds, Alignments;
 
   auto &&Subst = [&](Expr *E) -> ExprResult {
     if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
@@ -273,9 +273,21 @@ static void instantiateOMPDeclareSimdDec
     }
   }
 
-  (void)S.ActOnOpenMPDeclareSimdDirective(S.ConvertDeclToDeclGroup(New),
-                                          Attr.getBranchState(), Simdlen.get(),
-                                          Uniforms, Attr.getRange());
+  auto AI = Attr.alignments_begin();
+  for (auto *E : Attr.aligneds()) {
+    ExprResult Inst = Subst(E);
+    if (Inst.isInvalid())
+      continue;
+    Aligneds.push_back(Inst.get());
+    Inst = ExprEmpty();
+    if (*AI)
+      Inst = S.SubstExpr(*AI, TemplateArgs);
+    Alignments.push_back(Inst.get());
+    ++AI;
+  }
+  (void)S.ActOnOpenMPDeclareSimdDirective(
+      S.ConvertDeclToDeclGroup(New), Attr.getBranchState(), Simdlen.get(),
+      Uniforms, Aligneds, Alignments, Attr.getRange());
 }
 
 void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,

Modified: cfe/trunk/test/OpenMP/declare_simd_ast_print.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_ast_print.c?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/declare_simd_ast_print.c (original)
+++ cfe/trunk/test/OpenMP/declare_simd_ast_print.c Tue Apr 12 04:35:56 2016
@@ -6,16 +6,16 @@
 #ifndef HEADER
 #define HEADER
 
-#pragma omp declare simd
-#pragma omp declare simd simdlen(32)
+#pragma omp declare simd aligned(b : 64)
+#pragma omp declare simd simdlen(32) aligned(d, s1)
 #pragma omp declare simd inbranch, uniform(d)
 #pragma omp declare simd notinbranch simdlen(2), uniform(s1, s2)
-void add_1(float *d, float *s1, float *s2) __attribute__((cold));
+void add_1(float *d, float *s1, float *s2, double b[]) __attribute__((cold));
 
 // CHECK: #pragma omp declare simd notinbranch simdlen(2) uniform(s1, s2)
 // CHECK-NEXT: #pragma omp declare simd inbranch uniform(d)
-// CHECK-NEXT: #pragma omp declare simd simdlen(32)
-// CHECK-NEXT: #pragma omp declare simd
-// CHECK-NEXT: void add_1(float *d, float *s1, float *s2) __attribute__((cold))
+// CHECK-NEXT: #pragma omp declare simd simdlen(32) aligned(d) aligned(s1)
+// CHECK-NEXT: #pragma omp declare simd aligned(b: 64)
+// CHECK-NEXT: void add_1(float *d, float *s1, float *s2, double b[]) __attribute__((cold))
 
 #endif

Modified: cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/declare_simd_ast_print.cpp Tue Apr 12 04:35:56 2016
@@ -17,27 +17,27 @@ void add_1(float *d) __attribute__((cold
 // CHECK-NEXT: void add_1(float *d) __attribute__((cold));
 //
 
-#pragma omp declare simd
+#pragma omp declare simd aligned(hp, hp2)
 template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
 }
 
-// CHECK: #pragma omp declare simd
+// CHECK: #pragma omp declare simd aligned(hp) aligned(hp2)
 // CHECK-NEXT: template <class C = int> void h(int *hp, int *hp2, int *hq, int *lin) {
 // CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
 // CHECK-NEXT: }
 
-// CHECK: #pragma omp declare simd
+// CHECK: #pragma omp declare simd  aligned(hp) aligned(hp2)
 // CHECK-NEXT: template <class C = float> void h(float *hp, float *hp2, float *hq, float *lin) {
 // CHECK-NEXT: }
 
-// CHECK: #pragma omp declare simd
+// CHECK: #pragma omp declare simd aligned(hp) aligned(hp2)
 // CHECK: template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
 // CHECK-NEXT: }
 //
 
 // Explicit specialization with <C=int>.
 // Pragmas need to be same, otherwise standard says that's undefined behavior.
-#pragma omp declare simd
+#pragma omp declare simd aligned(hp, hp2)
 template <>
 void h(int *hp, int *hp2, int *hq, int *lin)
 {
@@ -55,31 +55,31 @@ class VV {
   #pragma omp declare simd uniform(this, a)
   int add(int a, int b) __attribute__((cold)) { return a + b; }
 
-  // CHECK: #pragma omp declare simd
-  // CHECK-NEXT: float taddpf(float *a, float *b)     {
+  // CHECK: #pragma omp declare simd aligned(b: 4) aligned(a)
+  // CHECK-NEXT: float taddpf(float *a, float *&b)     {
   // CHECK-NEXT: return *a + *b;
   // CHECK-NEXT: }
-  #pragma omp declare simd
-  float taddpf(float *a, float *b) { return *a + *b; }
+  #pragma omp declare simd aligned (b: 4) aligned(a)
+  float taddpf(float *a, float *&b) { return *a + *b; }
 
-// CHECK: #pragma omp declare simd
+// CHECK: #pragma omp declare simd aligned(b: 8)
 // CHECK-NEXT: #pragma omp declare simd
-// CHECK-NEXT: int tadd(int b) {
-// CHECK-NEXT: return this->x[b] + b;
+// CHECK-NEXT: int tadd(int (&b)[]) {
+// CHECK-NEXT: return this->x[b[0]] + b[0];
 // CHECK-NEXT: }
   #pragma omp declare simd
-  #pragma omp declare simd
-  int tadd(int b) { return x[b] + b; }
+  #pragma omp declare simd aligned(b : 8)
+  int tadd(int (&b)[]) { return x[b[0]] + b[0]; }
 
 private:
   int x[10];
 };
 
-// CHECK: template <int X = 16> class TVV {
+// CHECK: template <int X = 16, typename T = float> class TVV {
 // CHECK: #pragma omp declare simd
 // CHECK-NEXT: int tadd(int a, int b);
-// CHECK: #pragma omp declare simd
-// CHECK-NEXT: float taddpf(float *a, float *b) {
+// CHECK: #pragma omp declare simd aligned(a: 16 * 2) aligned(b)
+// CHECK-NEXT: float taddpf(float *a, float *&b) {
 // CHECK-NEXT: return *a + *b;
 // CHECK-NEXT: }
 // CHECK: #pragma omp declare simd
@@ -88,10 +88,10 @@ private:
 // CHECK-NEXT: return this->x[b] + b;
 // CHECK-NEXT: }
 // CHECK: }
-template <int X>
+template <int X, typename T>
 class TVV {
 public:
-// CHECK: template <int X> class TVV {
+// CHECK: template <int X, typename T> class TVV {
   #pragma omp declare simd simdlen(X)
   int tadd(int a, int b) { return a + b; }
 
@@ -100,11 +100,11 @@ public:
 // CHECK-NEXT: return a + b;
 // CHECK-NEXT: }
 
-  #pragma omp declare simd
-  float taddpf(float *a, float *b) { return *a + *b; }
+  #pragma omp declare simd aligned(a : X * 2) aligned(b)
+  float taddpf(float *a, T *&b) { return *a + *b; }
 
-// CHECK: #pragma omp declare simd
-// CHECK-NEXT: float taddpf(float *a, float *b) {
+// CHECK: #pragma omp declare simd aligned(a: X * 2) aligned(b)
+// CHECK-NEXT: float taddpf(float *a, T *&b) {
 // CHECK-NEXT: return *a + *b;
 // CHECK-NEXT: }
 
@@ -123,20 +123,21 @@ private:
 };
 // CHECK: };
 
-// CHECK: #pragma omp declare simd simdlen(64)
-// CHECK: template <int N = 64> void foo(int (&)[64])
-// CHECK: #pragma omp declare simd simdlen(N)
-// CHECK: template <int N> void foo(int (&)[N])
-#pragma omp declare simd simdlen(N)
+// CHECK: #pragma omp declare simd simdlen(64) aligned(b: 64 * 2)
+// CHECK: template <int N = 64> void foo(int (&b)[64])
+// CHECK: #pragma omp declare simd simdlen(N) aligned(b: N * 2)
+// CHECK: template <int N> void foo(int (&b)[N])
+#pragma omp declare simd simdlen(N) aligned(b : N * 2)
 template <int N>
-void foo(int (&)[N]);
+void foo(int (&b)[N]);
 
-// CHECK: TVV<16> t16;
-TVV<16> t16;
+// CHECK: TVV<16, float> t16;
+TVV<16, float> t16;
 
 void f() {
   float a = 1.0f, b = 2.0f;
-  float r = t16.taddpf(&a, &b);
+  float *p = &b;
+  float r = t16.taddpf(&a, p);
   int res = t16.tadd(b);
   int c[64];
   foo(c);

Modified: cfe/trunk/test/OpenMP/declare_simd_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_simd_messages.cpp?rev=266052&r1=266051&r2=266052&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/declare_simd_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/declare_simd_messages.cpp Tue Apr 12 04:35:56 2016
@@ -75,10 +75,10 @@ void h(int *hp, int *hp2, int *hq, int *
 #pragma omp declare simd simdlen() simdlen)
 void foo();
 
-// expected-error at +3 2 {{expected reference to one of the parameters of function 'foo'}}
+// expected-error at +3 4 {{expected reference to one of the parameters of function 'foo'}}
 // expected-error at +2 {{invalid use of 'this' outside of a non-static member function}}
 // expected-error at +1 {{argument to 'simdlen' clause must be a strictly positive integer value}}
-#pragma omp declare simd simdlen(N) uniform(this, var)
+#pragma omp declare simd simdlen(N) uniform(this, var) aligned(var)
 template<int N>
 void foo() {}
 
@@ -105,7 +105,46 @@ void test() {
 #pragma omp declare simd uniform(this,a
 // expected-error at +1 {{expected expression}}
 #pragma omp declare simd uniform(,a)
-void bar(int a);
+// expected-error at +1 {{expected '(' after 'aligned'}}
+#pragma omp declare simd aligned
+// expected-note at +3 {{to match this '('}}
+// expected-error at +2 {{expected ')'}}
+// expected-error at +1 {{expected expression}}
+#pragma omp declare simd aligned(
+// expected-error at +1 {{expected expression}}
+#pragma omp declare simd aligned()
+// expected-note at +3 {{to match this '('}}
+// expected-error at +2 {{expected ')'}}
+// expected-error at +1 {{expected expression}}
+#pragma omp declare simd aligned(a:
+// expected-error at +1 {{expected expression}}
+#pragma omp declare simd aligned(a:)
+// expected-warning at +2 {{extra tokens at the end of '#pragma omp declare simd' are ignored}}
+// expected-error at +1 {{expected '(' after 'aligned'}}
+#pragma omp declare simd aligned :)
+// expected-note at +3 {{to match this '('}}
+// expected-error at +2 {{expected ')'}}
+// expected-error at +1 {{invalid use of 'this' outside of a non-static member function}}
+#pragma omp declare simd aligned(this
+// expected-note at +3 {{to match this '('}}
+// expected-error at +2 {{expected ')'}}
+// expected-error at +1 {{invalid use of 'this' outside of a non-static member function}}
+#pragma omp declare simd aligned(this,b
+// expected-error at +1 {{expected expression}}
+#pragma omp declare simd aligned(, b)
+// expected-note at +4 {{defined as aligned}}
+// expected-error at +3 {{a parameter cannot appear in more than one aligned clause}}
+// expected-error at +2 {{expected expression}}
+// expected-error at +1 {{expected ',' or ')' in 'aligned' clause}}
+#pragma omp declare simd aligned(b) aligned(b ; 64)
+// expected-note at +2 {{defined as aligned}}
+// expected-error at +1 {{a parameter cannot appear in more than one aligned clause}}
+#pragma omp declare simd aligned(b) aligned(b: 64)
+// expected-error at +1 {{argument to 'aligned' clause must be a strictly positive integer value}}
+#pragma omp declare simd aligned(b: -1)
+// expected-warning at +1 {{aligned clause will be ignored because the requested alignment is not a power of 2}}
+#pragma omp declare simd aligned(b: 3)
+void bar(int a, int *b);
 
 template <class T>
 struct St {
@@ -113,8 +152,11 @@ struct St {
 #pragma init_seg(compiler)
 #pragma omp declare simd
 #pragma init_seg(compiler)
+// expected-note at +4 {{defined as aligned}}
+// expected-error at +3 {{argument to 'aligned' clause must be a strictly positive integer value}}
+// expected-error at +2 {{'this' cannot appear in more than one aligned clause}}
 // expected-error at +1 {{use of undeclared identifier 't'}}
-#pragma omp declare simd uniform(this, t)
+#pragma omp declare simd uniform(this, t) aligned(this: 4) aligned(this: -4)
   void h(T *hp) {
 // expected-error at +1 {{unexpected OpenMP directive '#pragma omp declare simd'}}
 #pragma omp declare simd




More information about the cfe-commits mailing list