]> granicus.if.org Git - clang/commitdiff
[OPENMP 4.0] Support for 'aligned' clause in 'declare simd' directive.
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 12 Apr 2016 09:35:56 +0000 (09:35 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 12 Apr 2016 09:35:56 +0000 (09:35 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@266052 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Parse/ParseOpenMP.cpp
lib/Sema/SemaOpenMP.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/OpenMP/declare_simd_ast_print.c
test/OpenMP/declare_simd_ast_print.cpp
test/OpenMP/declare_simd_messages.cpp

index 5fcd2e9458e2be78fda3f7234c73c14e54fd2579..87654caf63bf63e138914c6160a6402ac210e1cb 100644 (file)
@@ -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;
+      }
     }
   }];
 }
index 76cf5c947ce7bd8a252163354d13128ea56e0e16..dd1f7c3ad70cf0be2523aa6441cf6b7a9a829352 100644 (file)
@@ -7950,7 +7950,7 @@ def err_omp_aligned_expected_array_or_ptr : Error<
   "%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<
index 54a3ed56d6f58d070fd9fbb2f243f86aa7d1a4e1..7099a2b86a0d585a29f0ddd93647f3e66166cfc1 100644 (file)
@@ -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,
index 6112c90cacda028e51ebf36870c69e14531fe21d..b41a2a86f5149ff9e4f119a5913510bd2ab57092 100644 (file)
@@ -329,63 +329,6 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
                                                          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(Parser::DeclGroupPtrTy Ptr,
       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(Parser::DeclGroupPtrTy Ptr,
   }
   // 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;
 }
 
index 43a774eec665aabf458369cd276eca478611fcf1..287bb3681840260a3fa732a53a9d8a22a6414b7a 100644 (file)
@@ -3192,7 +3192,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
 
 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::ActOnOpenMPDeclareSimdDirective(
     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::ActOnOpenMPAlignedClause(
     // 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;
index 168bf6f451d8af14d7a8df8cfdd2af797d4a0553..3a320e11d143b297e1f74c2477467df6f8fc929e 100644 (file)
@@ -247,7 +247,7 @@ static void instantiateOMPDeclareSimdDeclAttr(
     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 instantiateOMPDeclareSimdDeclAttr(
     }
   }
 
-  (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,
index fe6bffcf89ad8497bdc25f7387ff48e5d6cba2d5..5cb24084e535b564b37053ce7dbc84c5ff7401a0 100644 (file)
@@ -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
index e38ebe9613ce2aa65964ed0187bf028962d59d77..56008b53967ddd78877be27ad4f26dbb2cbad460 100644 (file)
@@ -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);
index 70737ad2685a640e161ce274e8100bac912fdd68..e1745aaa1164e03ec65b87a26b1fd2ffe6be4ba6 100644 (file)
@@ -75,10 +75,10 @@ void h(int *hp, int *hp2, int *hq, int *lin) {
 #pragma omp declare simd simdlen() simdlen)
 void foo();
 
-// expected-error@+3 2 {{expected reference to one of the parameters of function 'foo'}}
+// expected-error@+3 4 {{expected reference to one of the parameters of function 'foo'}}
 // expected-error@+2 {{invalid use of 'this' outside of a non-static member function}}
 // expected-error@+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@+1 {{expected expression}}
 #pragma omp declare simd uniform(,a)
-void bar(int a);
+// expected-error@+1 {{expected '(' after 'aligned'}}
+#pragma omp declare simd aligned
+// expected-note@+3 {{to match this '('}}
+// expected-error@+2 {{expected ')'}}
+// expected-error@+1 {{expected expression}}
+#pragma omp declare simd aligned(
+// expected-error@+1 {{expected expression}}
+#pragma omp declare simd aligned()
+// expected-note@+3 {{to match this '('}}
+// expected-error@+2 {{expected ')'}}
+// expected-error@+1 {{expected expression}}
+#pragma omp declare simd aligned(a:
+// expected-error@+1 {{expected expression}}
+#pragma omp declare simd aligned(a:)
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp declare simd' are ignored}}
+// expected-error@+1 {{expected '(' after 'aligned'}}
+#pragma omp declare simd aligned :)
+// expected-note@+3 {{to match this '('}}
+// expected-error@+2 {{expected ')'}}
+// expected-error@+1 {{invalid use of 'this' outside of a non-static member function}}
+#pragma omp declare simd aligned(this
+// expected-note@+3 {{to match this '('}}
+// expected-error@+2 {{expected ')'}}
+// expected-error@+1 {{invalid use of 'this' outside of a non-static member function}}
+#pragma omp declare simd aligned(this,b
+// expected-error@+1 {{expected expression}}
+#pragma omp declare simd aligned(, b)
+// expected-note@+4 {{defined as aligned}}
+// expected-error@+3 {{a parameter cannot appear in more than one aligned clause}}
+// expected-error@+2 {{expected expression}}
+// expected-error@+1 {{expected ',' or ')' in 'aligned' clause}}
+#pragma omp declare simd aligned(b) aligned(b ; 64)
+// expected-note@+2 {{defined as aligned}}
+// expected-error@+1 {{a parameter cannot appear in more than one aligned clause}}
+#pragma omp declare simd aligned(b) aligned(b: 64)
+// expected-error@+1 {{argument to 'aligned' clause must be a strictly positive integer value}}
+#pragma omp declare simd aligned(b: -1)
+// expected-warning@+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@+4 {{defined as aligned}}
+// expected-error@+3 {{argument to 'aligned' clause must be a strictly positive integer value}}
+// expected-error@+2 {{'this' cannot appear in more than one aligned clause}}
 // expected-error@+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@+1 {{unexpected OpenMP directive '#pragma omp declare simd'}}
 #pragma omp declare simd