diff options
-rw-r--r-- | clang/include/clang/Basic/Attr.td | 14 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 137 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 75 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 20 | ||||
-rw-r--r-- | clang/test/OpenMP/declare_simd_ast_print.c | 12 | ||||
-rw-r--r-- | clang/test/OpenMP/declare_simd_ast_print.cpp | 65 | ||||
-rw-r--r-- | clang/test/OpenMP/declare_simd_messages.cpp | 50 |
9 files changed, 266 insertions, 112 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5fcd2e9458e..87654caf63b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -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; + } } }]; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 76cf5c947ce..dd1f7c3ad70 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 54a3ed56d6f..7099a2b86a0 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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, diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 6112c90cacd..b41a2a86f51 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 43a774eec66..287bb368184 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -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; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 168bf6f451d..3a320e11d14 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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, diff --git a/clang/test/OpenMP/declare_simd_ast_print.c b/clang/test/OpenMP/declare_simd_ast_print.c index fe6bffcf89a..5cb24084e53 100644 --- a/clang/test/OpenMP/declare_simd_ast_print.c +++ b/clang/test/OpenMP/declare_simd_ast_print.c @@ -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 diff --git a/clang/test/OpenMP/declare_simd_ast_print.cpp b/clang/test/OpenMP/declare_simd_ast_print.cpp index e38ebe9613c..56008b53967 100644 --- a/clang/test/OpenMP/declare_simd_ast_print.cpp +++ b/clang/test/OpenMP/declare_simd_ast_print.cpp @@ -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); diff --git a/clang/test/OpenMP/declare_simd_messages.cpp b/clang/test/OpenMP/declare_simd_messages.cpp index 70737ad2685..e1745aaa116 100644 --- a/clang/test/OpenMP/declare_simd_messages.cpp +++ b/clang/test/OpenMP/declare_simd_messages.cpp @@ -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 |