diff options
author | Alexander Musman <alexander.musman@gmail.com> | 2014-04-22 13:09:42 +0000 |
---|---|---|
committer | Alexander Musman <alexander.musman@gmail.com> | 2014-04-22 13:09:42 +0000 |
commit | 8dba66412b0a7dba4a07de30fb74eabd37a69e79 (patch) | |
tree | 263fd67f395fb278ebf7289e61f9bb24dfc08271 /clang/lib | |
parent | 761aa37e3efb3f3371acd486c6ec5f5e89a36ea3 (diff) | |
download | bcm5719-llvm-8dba66412b0a7dba4a07de30fb74eabd37a69e79.tar.gz bcm5719-llvm-8dba66412b0a7dba4a07de30fb74eabd37a69e79.zip |
[OPENMP] parsing 'linear' clause (for directive 'omp simd')
Differential Revision: http://reviews.llvm.org/D3272
llvm-svn: 206891
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 24 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 12 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Basic/OpenMPKinds.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 140 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 32 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 9 |
9 files changed, 267 insertions, 12 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index a03ef00ce76..8e937fb08b1 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1192,6 +1192,30 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPSharedClause(N); } +OMPLinearClause *OMPLinearClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL, Expr *Step) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (VL.size() + 1)); + OMPLinearClause *Clause = new (Mem) + OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setStep(Step); + return Clause; +} + +OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, + unsigned NumVars) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (NumVars + 1)); + return new (Mem) OMPLinearClause(NumVars); +} + OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 5cfaab26e53..758db448288 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -664,6 +664,18 @@ void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) { } } +void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { + if (!Node->varlist_empty()) { + OS << "linear"; + VisitOMPClauseList(Node, '('); + if (Node->getStep() != 0) { + OS << ": "; + Node->getStep()->printPretty(OS, 0, Policy, 0); + } + OS << ")"; + } +} + void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) { if (!Node->varlist_empty()) { OS << "copyin"; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 07ed86a91cd..1a6d1812dca 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -297,6 +297,10 @@ void OMPClauseProfiler::VisitOMPFirstprivateClause( void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { + VisitOMPClauseList(C); + Profiler->VisitStmt(C->getStep()); +} void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) { VisitOMPClauseList(C); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index ec09de1eb3b..6a7f89069a6 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -83,6 +83,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_private: case OMPC_firstprivate: case OMPC_shared: + case OMPC_linear: case OMPC_copyin: case NUM_OPENMP_CLAUSES: break; @@ -110,6 +111,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_private: case OMPC_firstprivate: case OMPC_shared: + case OMPC_linear: case OMPC_copyin: case NUM_OPENMP_CLAUSES: break; diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index f1b61077b37..bf3753fd814 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -258,7 +258,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// /// clause: /// if-clause | num_threads-clause | safelen-clause | default-clause | -/// private-clause | firstprivate-clause | shared-clause +/// private-clause | firstprivate-clause | shared-clause | linear-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -301,6 +301,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_private: case OMPC_firstprivate: case OMPC_shared: + case OMPC_linear: case OMPC_copyin: Clause = ParseOpenMPVarListClause(CKind); break; @@ -392,10 +393,13 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { /// 'firstprivate' '(' list ')' /// shared-clause: /// 'shared' '(' list ')' +/// linear-clause: +/// 'linear' '(' list [ ':' linear-step ] ')' /// OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); + SourceLocation ColonLoc = SourceLocation(); // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, @@ -404,8 +408,10 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SmallVector<Expr *, 5> Vars; bool IsComma = true; - while (IsComma || (Tok.isNot(tok::r_paren) && + const bool MayHaveTail = (Kind == OMPC_linear); + while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { + ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); // Parse variable ExprResult VarExpr = ParseAssignmentExpression(); if (VarExpr.isUsable()) { @@ -416,21 +422,34 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { } // Skip ',' if any IsComma = Tok.is(tok::comma); - if (IsComma) { + if (IsComma) ConsumeToken(); - } else if (Tok.isNot(tok::r_paren) && - Tok.isNot(tok::annot_pragma_openmp_end)) { - Diag(Tok, diag::err_omp_expected_punc) - << getOpenMPClauseName(Kind); - } + else if (Tok.isNot(tok::r_paren) && + Tok.isNot(tok::annot_pragma_openmp_end) && + (!MayHaveTail || Tok.isNot(tok::colon))) + Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind); + } + + // Parse ':' linear-step + Expr *TailExpr = 0; + const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); + if (MustHaveTail) { + ColonLoc = Tok.getLocation(); + ConsumeToken(); + ExprResult Tail = ParseAssignmentExpression(); + if (Tail.isUsable()) + TailExpr = Tail.take(); + else + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); } // Parse ')'. T.consumeClose(); - if (Vars.empty()) + if (Vars.empty() || (MustHaveTail && !TailExpr)) return 0; - return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen, - Tok.getLocation()); + return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen, + ColonLoc, Tok.getLocation()); } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index b70a9c8dc2b..0c592a61441 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -294,9 +294,10 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) { if (Kind != OMPD_parallel) { if (isOpenMPLocal(D, std::next(Stack.rbegin())) && D->isLocalVarDecl() && (D->getStorageClass() == SC_Auto || - D->getStorageClass() == SC_None)) + D->getStorageClass() == SC_None)) { DVar.CKind = OMPC_private; return DVar; + } } // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced @@ -774,6 +775,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, case OMPC_private: case OMPC_firstprivate: case OMPC_shared: + case OMPC_linear: case OMPC_copyin: case OMPC_threadprivate: case OMPC_unknown: @@ -929,6 +931,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, case OMPC_private: case OMPC_firstprivate: case OMPC_shared: + case OMPC_linear: case OMPC_copyin: case OMPC_threadprivate: case OMPC_unknown: @@ -986,8 +989,10 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind, OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, + Expr *TailExpr, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc) { OMPClause *Res = 0; switch (Kind) { @@ -1000,6 +1005,10 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, case OMPC_shared: Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc); break; + case OMPC_linear: + Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc, + ColonLoc, EndLoc); + break; case OMPC_copyin: Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc); break; @@ -1382,6 +1391,135 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); } +OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc) { + SmallVector<Expr *, 8> Vars; + for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); + I != E; ++I) { + assert(*I && "NULL expr in OpenMP linear clause."); + if (isa<DependentScopeDeclRefExpr>(*I)) { + // It will be analyzed later. + Vars.push_back(*I); + 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 = (*I)->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>(*I); + if (!DE || !isa<VarDecl>(DE->getDecl())) { + Diag(ELoc, diag::err_omp_expected_var_name) << (*I)->getSourceRange(); + continue; + } + + VarDecl *VD = cast<VarDecl>(DE->getDecl()); + + // 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); + if (DVar.RefExpr) { + Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_linear); + Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(DVar.CKind); + continue; + } + + QualType QType = VD->getType(); + if (QType->isDependentType() || QType->isInstantiationDependentType()) { + // It will be analyzed later. + Vars.push_back(DE); + continue; + } + + // A variable must not have an incomplete type or a reference type. + if (RequireCompleteType(ELoc, QType, + diag::err_omp_linear_incomplete_type)) { + continue; + } + if (QType->isReferenceType()) { + Diag(ELoc, diag::err_omp_clause_ref_type_arg) + << getOpenMPClauseName(OMPC_linear) << QType; + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + + // A list item must not be const-qualified. + if (QType.isConstant(Context)) { + Diag(ELoc, diag::err_omp_const_variable) + << getOpenMPClauseName(OMPC_linear); + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + + // A list item must be of integral or pointer type. + QType = QType.getUnqualifiedType().getCanonicalType(); + const Type *Ty = QType.getTypePtrOrNull(); + if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) && + !Ty->isPointerType())) { + Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType; + bool IsDecl = + VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; + Diag(VD->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << VD; + continue; + } + + DSAStack->addDSA(VD, DE, OMPC_linear); + Vars.push_back(DE); + } + + if (Vars.empty()) + return 0; + + Expr *StepExpr = Step; + if (Step && !Step->isValueDependent() && !Step->isTypeDependent() && + !Step->isInstantiationDependent() && + !Step->containsUnexpandedParameterPack()) { + SourceLocation StepLoc = Step->getLocStart(); + ExprResult Val = PerformImplicitIntegerConversion(StepLoc, Step); + if (Val.isInvalid()) + return 0; + StepExpr = Val.take(); + + // Warn about zero linear step (it would be probably better specified as + // making corresponding variables 'const'). + llvm::APSInt Result; + if (StepExpr->isIntegerConstantExpr(Result, Context) && + !Result.isNegative() && !Result.isStrictlyPositive()) + Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] + << (Vars.size() > 1); + } + + return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc, + Vars, StepExpr); +} + OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 22913104d74..f1138918825 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1382,6 +1382,19 @@ public: EndLoc); } + /// \brief Build a new OpenMP 'linear' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc, + ColonLoc, EndLoc); + } + /// \brief Build a new OpenMP 'copyin' clause. /// /// By default, performs semantic analysis to build the new statement. @@ -6436,6 +6449,25 @@ TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) { template<typename Derived> OMPClause * +TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) { + llvm::SmallVector<Expr *, 16> Vars; + Vars.reserve(C->varlist_size()); + for (auto *VE : C->varlists()) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE)); + if (EVar.isInvalid()) + return 0; + Vars.push_back(EVar.take()); + } + ExprResult Step = getDerived().TransformExpr(C->getStep()); + if (Step.isInvalid()) + return 0; + return getDerived().RebuildOMPLinearClause( + Vars, Step.take(), C->getLocStart(), C->getLParenLoc(), C->getColonLoc(), + C->getLocEnd()); +} + +template<typename Derived> +OMPClause * TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) { llvm::SmallVector<Expr *, 16> Vars; Vars.reserve(C->varlist_size()); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 9a201d0f69b..da652ff8e3f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1692,6 +1692,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_shared: C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]); break; + case OMPC_linear: + C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]); + break; case OMPC_copyin: C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]); break; @@ -1755,6 +1758,18 @@ void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) { C->setVarRefs(Vars); } +void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setColonLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); + C->setStep(Reader->Reader.ReadSubExpr()); +} + void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index bbbd3377cb7..958620636ee 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1716,6 +1716,15 @@ void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) { Writer->Writer.AddStmt(VE); } +void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getColonLoc(), Record); + for (auto *VE : C->varlists()) + Writer->Writer.AddStmt(VE); + Writer->Writer.AddStmt(C->getStep()); +} + void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); |