Author: Mike Rice Date: 2021-11-04T14:40:30-07:00 New Revision: 4eac7bcf1af1a94d76aec8d54f4a0f0014dd121c
URL: https://github.com/llvm/llvm-project/commit/4eac7bcf1af1a94d76aec8d54f4a0f0014dd121c DIFF: https://github.com/llvm/llvm-project/commit/4eac7bcf1af1a94d76aec8d54f4a0f0014dd121c.diff LOG: [OpenMP] Add parsing/sema/serialization for 'bind' clause. Differential Revision: https://reviews.llvm.org/D113154 Added: Modified: clang/include/clang/AST/OpenMPClause.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/Basic/OpenMPKinds.def clang/include/clang/Basic/OpenMPKinds.h clang/include/clang/Sema/Sema.h clang/lib/AST/OpenMPClause.cpp clang/lib/AST/StmtProfile.cpp clang/lib/Basic/OpenMPKinds.cpp clang/lib/CodeGen/CGStmtOpenMP.cpp clang/lib/Parse/ParseOpenMP.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/OpenMP/generic_loop_ast_print.cpp clang/test/OpenMP/generic_loop_messages.cpp clang/tools/libclang/CIndex.cpp flang/lib/Semantics/check-omp-structure.cpp llvm/include/llvm/Frontend/OpenMP/OMP.td Removed: ################################################################################ diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 749eff57313a..99554641a64b 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -8405,6 +8405,96 @@ class OMPFilterClause final : public OMPClause, public OMPClauseWithPreInit { } }; +/// This represents 'bind' clause in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp loop bind(parallel) +/// \endcode +class OMPBindClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// The binding kind of 'bind' clause. + OpenMPBindClauseKind Kind = OMPC_BIND_unknown; + + /// Start location of the kind in source code. + SourceLocation KindLoc; + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Set the binding kind. + void setBindKind(OpenMPBindClauseKind K) { Kind = K; } + + /// Set the binding kind location. + void setBindKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } + + /// Build 'bind' clause with kind \a K ('teams', 'parallel', or 'thread'). + /// + /// \param K Binding kind of the clause ('teams', 'parallel' or 'thread'). + /// \param KLoc Starting location of the binding kind. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPBindClause(OpenMPBindClauseKind K, SourceLocation KLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_bind, StartLoc, EndLoc), LParenLoc(LParenLoc), + Kind(K), KindLoc(KLoc) {} + + /// Build an empty clause. + OMPBindClause() + : OMPClause(llvm::omp::OMPC_bind, SourceLocation(), SourceLocation()) {} + +public: + /// Build 'bind' clause with kind \a K ('teams', 'parallel', or 'thread'). + /// + /// \param C AST context + /// \param K Binding kind of the clause ('teams', 'parallel' or 'thread'). + /// \param KLoc Starting location of the binding kind. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + static OMPBindClause *Create(const ASTContext &C, OpenMPBindClauseKind K, + SourceLocation KLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc); + + /// Build an empty 'bind' clause. + /// + /// \param C AST context + static OMPBindClause *CreateEmpty(const ASTContext &C); + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns kind of the clause. + OpenMPBindClauseKind getBindKind() const { return Kind; } + + /// Returns location of clause kind. + SourceLocation getBindKindLoc() const { return KindLoc; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_bind; + } +}; + /// This class implements a simple visitor for OMPClause /// subclasses. template<class ImplClass, template <typename> class Ptr, typename RetTy> diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index fe26a1de9f85..67f0c2758baf 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -3676,6 +3676,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPFilterClause(OMPFilterClause *C) { return true; } +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPBindClause(OMPBindClause *C) { + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index a19daf91578e..80ebda917945 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -62,6 +62,9 @@ #ifndef OPENMP_ADJUST_ARGS_KIND #define OPENMP_ADJUST_ARGS_KIND(Name) #endif +#ifndef OPENMP_BIND_KIND +#define OPENMP_BIND_KIND(Name) +#endif // Static attributes for 'schedule' clause. OPENMP_SCHEDULE_KIND(static) @@ -156,6 +159,12 @@ OPENMP_REDUCTION_MODIFIER(task) OPENMP_ADJUST_ARGS_KIND(nothing) OPENMP_ADJUST_ARGS_KIND(need_device_ptr) +// Binding kinds for the 'bind' clause. +OPENMP_BIND_KIND(teams) +OPENMP_BIND_KIND(parallel) +OPENMP_BIND_KIND(thread) + +#undef OPENMP_BIND_KIND #undef OPENMP_ADJUST_ARGS_KIND #undef OPENMP_REDUCTION_MODIFIER #undef OPENMP_DEVICE_MODIFIER diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h index 269f8d96f0bb..e95a717f268d 100644 --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -174,6 +174,13 @@ enum OpenMPAdjustArgsOpKind { OMPC_ADJUST_ARGS_unknown, }; +/// OpenMP bindings for the 'bind' clause. +enum OpenMPBindClauseKind { +#define OPENMP_BIND_KIND(Name) OMPC_BIND_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_BIND_unknown +}; + unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts); const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 62f6dcc8966b..b22d8530ed6c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11424,6 +11424,12 @@ class Sema final { SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators); + /// Called on a well-formed 'bind' clause. + OMPClause *ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// The kind of conversion being performed. enum CheckedConversionKind { diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 176c04072783..ddc31aa9e93f 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -161,6 +161,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_bind: break; default: break; @@ -259,6 +260,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_bind: break; default: break; @@ -1586,6 +1588,16 @@ OMPInitClause *OMPInitClause::CreateEmpty(const ASTContext &C, unsigned N) { return new (Mem) OMPInitClause(N); } +OMPBindClause * +OMPBindClause::Create(const ASTContext &C, OpenMPBindClauseKind K, + SourceLocation KLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) { + return new (C) OMPBindClause(K, KLoc, StartLoc, LParenLoc, EndLoc); +} + +OMPBindClause *OMPBindClause::CreateEmpty(const ASTContext &C) { + return new (C) OMPBindClause(); +} //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// @@ -2297,6 +2309,12 @@ void OMPClausePrinter::VisitOMPFilterClause(OMPFilterClause *Node) { OS << ")"; } +void OMPClausePrinter::VisitOMPBindClause(OMPBindClause *Node) { + OS << "bind(" + << getOpenMPSimpleClauseTypeName(OMPC_bind, unsigned(Node->getBindKind())) + << ")"; +} + void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx, VariantMatchInfo &VMI) const { for (const OMPTraitSet &Set : Sets) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 4ea4322bfd0f..97bc7e6aabeb 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -878,6 +878,7 @@ void OMPClauseProfiler::VisitOMPAffinityClause(const OMPAffinityClause *C) { Profiler->VisitStmt(E); } void OMPClauseProfiler::VisitOMPOrderClause(const OMPOrderClause *C) {} +void OMPClauseProfiler::VisitOMPBindClause(const OMPBindClause *C) {} } // namespace void diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 5b01bf863bb0..9e74e05bd863 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -130,6 +130,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str, #define OPENMP_ADJUST_ARGS_KIND(Name) .Case(#Name, OMPC_ADJUST_ARGS_##Name) #include "clang/Basic/OpenMPKinds.def" .Default(OMPC_ADJUST_ARGS_unknown); + case OMPC_bind: + return llvm::StringSwitch<unsigned>(Str) +#define OPENMP_BIND_KIND(Name) .Case(#Name, OMPC_BIND_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_BIND_unknown); case OMPC_unknown: case OMPC_threadprivate: case OMPC_if: @@ -385,6 +390,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, #include "clang/Basic/OpenMPKinds.def" } llvm_unreachable("Invalid OpenMP 'adjust_args' clause kind"); + case OMPC_bind: + switch (Type) { + case OMPC_BIND_unknown: + return "unknown"; +#define OPENMP_BIND_KIND(Name) \ + case OMPC_BIND_##Name: \ + return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'bind' clause type"); case OMPC_unknown: case OMPC_threadprivate: case OMPC_if: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index b80f663a50a5..4d4037001ee0 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -5992,6 +5992,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_adjust_args: case OMPC_append_args: case OMPC_memory_order: + case OMPC_bind: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index d0114b8fdae7..5444969f110f 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -3056,7 +3056,7 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { /// clause: /// if-clause | final-clause | num_threads-clause | safelen-clause | /// default-clause | private-clause | firstprivate-clause | shared-clause -/// | linear-clause | aligned-clause | collapse-clause | +/// | linear-clause | aligned-clause | collapse-clause | bind-clause | /// lastprivate-clause | reduction-clause | proc_bind-clause | /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | /// mergeable-clause | flush-clause | read-clause | write-clause | @@ -3146,6 +3146,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_proc_bind: case OMPC_atomic_default_mem_order: case OMPC_order: + case OMPC_bind: // OpenMP [2.14.3.1, Restrictions] // Only a single default clause may be specified on a parallel, task or // teams directive. @@ -3154,6 +3155,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, // OpenMP [5.0, Requires directive, Restrictions] // At most one atomic_default_mem_order clause can appear // on the directive + // OpenMP 5.1, 2.11.7 loop Construct, Restrictions. + // At most one bind clause can appear on a loop directive. if (!FirstClause && CKind != OMPC_order) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; @@ -3500,6 +3503,9 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind, /// proc_bind-clause: /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' /// +/// bind-clause: +/// 'bind' '(' 'teams' | 'parallel' | 'thread' ')' +/// /// update-clause: /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')' /// diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 888113cf93d8..446132886ee0 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4687,6 +4687,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, + OpenMPBindClauseKind BindKind, SourceLocation StartLoc) { if (Stack->getCurScope()) { OpenMPDirectiveKind ParentRegion = Stack->getParentDirective(); @@ -4897,6 +4898,16 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, CurrentRegion != OMPD_loop; Recommend = ShouldBeInParallelRegion; } + if (!NestingProhibited && CurrentRegion == OMPD_loop) { + // OpenMP [5.1, 2.11.7, loop Construct, Restrictions] + // If the bind clause is present on the loop construct and binding is + // teams then the corresponding loop region must be strictly nested inside + // a teams region. + NestingProhibited = BindKind == OMPC_BIND_teams && + ParentRegion != OMPD_teams && + ParentRegion != OMPD_target_teams; + Recommend = ShouldBeInTeamsRegion; + } if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) { // OpenMP 4.5 [2.17 Nesting of Regions] @@ -5770,10 +5781,14 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { StmtResult Res = StmtError(); + OpenMPBindClauseKind BindKind = OMPC_BIND_unknown; + if (const OMPBindClause *BC = + OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses)) + BindKind = BC->getBindKind(); // First check CancelRegion which is then used in checkNestingOfRegions. if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) || checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion, - StartLoc)) + BindKind, StartLoc)) return StmtError(); llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit; @@ -6352,6 +6367,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_exclusive: case OMPC_uses_allocators: case OMPC_affinity: + case OMPC_bind: continue; case OMPC_allocator: case OMPC_flush: @@ -13460,6 +13476,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_bind: default: llvm_unreachable("Clause is not allowed."); } @@ -14290,6 +14307,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_exclusive: case OMPC_uses_allocators: case OMPC_affinity: + case OMPC_bind: default: llvm_unreachable("Unexpected OpenMP clause."); } @@ -14681,6 +14699,10 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; + case OMPC_bind: + Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -15047,6 +15069,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_bind: default: llvm_unreachable("Clause is not allowed."); } @@ -15840,6 +15863,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_detach: case OMPC_uses_allocators: case OMPC_when: + case OMPC_bind: default: llvm_unreachable("Clause is not allowed."); } @@ -21521,3 +21545,20 @@ OMPClause *Sema::ActOnOpenMPAffinityClause( return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Modifier, Vars); } + +OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (Kind == OMPC_BIND_unknown) { + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_bind, /*First=*/0, + /*Last=*/unsigned(OMPC_BIND_unknown)) + << getOpenMPClauseName(OMPC_bind); + return nullptr; + } + + return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc, + EndLoc); +} diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index cfc6e608bc59..ad61a6782976 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2256,6 +2256,19 @@ class TreeTransform { EndLoc); } + /// Build a new OpenMP 'bind' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide diff erent behavior. + OMPClause *RebuildOMPBindClause(OpenMPBindClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPBindClause(Kind, KindLoc, StartLoc, LParenLoc, + EndLoc); + } + /// Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -10242,6 +10255,13 @@ OMPClause *TreeTransform<Derived>::TransformOMPOrderClause(OMPOrderClause *C) { C->getEndLoc()); } +template <typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPBindClause(OMPBindClause *C) { + return getDerived().RebuildOMPBindClause( + C->getBindKind(), C->getBindKindLoc(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 07a0f00aa535..fdf75b0d7be9 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11971,6 +11971,9 @@ OMPClause *OMPClauseReader::readClause() { case llvm::omp::OMPC_filter: C = new (Context) OMPFilterClause(); break; + case llvm::omp::OMPC_bind: + C = OMPBindClause::CreateEmpty(Context); + break; #define OMP_CLAUSE_NO_CLASS(Enum, Str) \ case llvm::omp::Enum: \ break; @@ -12955,6 +12958,12 @@ void OMPClauseReader::VisitOMPFilterClause(OMPFilterClause *C) { C->setLParenLoc(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPBindClause(OMPBindClause *C) { + C->setBindKind(Record.readEnum<OpenMPBindClauseKind>()); + C->setLParenLoc(Record.readSourceLocation()); + C->setBindKindLoc(Record.readSourceLocation()); +} + OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() { OMPTraitInfo &TI = getContext().getNewOMPTraitInfo(); TI.Sets.resize(readUInt32()); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 3e0e5e9c8f75..4845dc70469f 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6732,6 +6732,12 @@ void OMPClauseWriter::VisitOMPAffinityClause(OMPAffinityClause *C) { Record.AddStmt(E); } +void OMPClauseWriter::VisitOMPBindClause(OMPBindClause *C) { + Record.writeEnum(C->getBindKind()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getBindKindLoc()); +} + void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) { writeUInt32(TI->Sets.size()); for (const auto &Set : TI->Sets) { diff --git a/clang/test/OpenMP/generic_loop_ast_print.cpp b/clang/test/OpenMP/generic_loop_ast_print.cpp index 7f5f53003e40..e887a969aac4 100644 --- a/clang/test/OpenMP/generic_loop_ast_print.cpp +++ b/clang/test/OpenMP/generic_loop_ast_print.cpp @@ -23,7 +23,7 @@ //PRINT: template <typename T, int C> void templ_foo(T t) { //PRINT: T j, z; -//PRINT: #pragma omp loop collapse(C) reduction(+: z) lastprivate(j) +//PRINT: #pragma omp loop collapse(C) reduction(+: z) lastprivate(j) bind(thread) //PRINT: for (T i = 0; i < t; ++i) //PRINT: for (j = 0; j < t; ++j) //PRINT: z += i + j; @@ -38,12 +38,13 @@ //DUMP: DeclRefExpr{{.*}}'z' 'T' //DUMP: OMPLastprivateClause //DUMP: DeclRefExpr{{.*}}'j' 'T' +//DUMP: OMPBindClause //DUMP: ForStmt //DUMP: ForStmt //PRINT: template<> void templ_foo<int, 2>(int t) { //PRINT: int j, z; -//PRINT: #pragma omp loop collapse(2) reduction(+: z) lastprivate(j) +//PRINT: #pragma omp loop collapse(2) reduction(+: z) lastprivate(j) bind(thread) //PRINT: for (int i = 0; i < t; ++i) //PRINT: for (j = 0; j < t; ++j) //PRINT: z += i + j; @@ -60,12 +61,13 @@ //DUMP: DeclRefExpr{{.*}}'z' 'int':'int' //DUMP: OMPLastprivateClause //DUMP: DeclRefExpr{{.*}}'j' 'int':'int' +//DUMP: OMPBindClause //DUMP: ForStmt template <typename T, int C> void templ_foo(T t) { T j,z; - #pragma omp loop collapse(C) reduction(+:z) lastprivate(j) + #pragma omp loop collapse(C) reduction(+:z) lastprivate(j) bind(thread) for (T i = 0; i<t; ++i) for (j = 0; j<t; ++j) z += i+j; @@ -109,7 +111,7 @@ void test() { } int j, z, z1; - //PRINT: #pragma omp loop collapse(2) private(z) lastprivate(j) order(concurrent) reduction(+: z1) + //PRINT: #pragma omp loop collapse(2) private(z) lastprivate(j) order(concurrent) reduction(+: z1) bind(parallel) //DUMP: OMPGenericLoopDirective //DUMP: OMPCollapseClause //DUMP: IntegerLiteral{{.*}}2 @@ -120,10 +122,11 @@ void test() { //DUMP: OMPOrderClause //DUMP: OMPReductionClause //DUMP-NEXT: DeclRefExpr{{.*}}'z1' + //DUMP: OMPBindClause //DUMP: ForStmt //DUMP: ForStmt #pragma omp loop collapse(2) private(z) lastprivate(j) order(concurrent) \ - reduction(+:z1) + reduction(+:z1) bind(parallel) for (auto i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { z = i+j; @@ -131,6 +134,40 @@ void test() { z1 += z; } } + + //PRINT: #pragma omp target teams + //PRINT: #pragma omp loop bind(teams) + //DUMP: OMPTargetTeamsDirective + //DUMP: OMPGenericLoopDirective + //DUMP: OMPBindClause + //DUMP: ForStmt + #pragma omp target teams + #pragma omp loop bind(teams) + for (auto i = 0; i < N; ++i) { } + + //PRINT: #pragma omp target + //PRINT: #pragma omp teams + //PRINT: #pragma omp loop bind(teams) + //DUMP: OMPTargetDirective + //DUMP: OMPTeamsDirective + //DUMP: OMPGenericLoopDirective + //DUMP: OMPBindClause + //DUMP: ForStmt + #pragma omp target + #pragma omp teams + #pragma omp loop bind(teams) + for (auto i = 0; i < N; ++i) { } +} + +//PRINT: void nobindingfunc() { +//DUMP: FunctionDecl {{.*}}nobindingfunc 'void ()' +void nobindingfunc() +{ + //PRINT: #pragma omp loop + //DUMP: OMPGenericLoopDirective + //DUMP: ForStmt + #pragma omp loop + for (int i=0; i<10; ++i) { } } void bar() diff --git a/clang/test/OpenMP/generic_loop_messages.cpp b/clang/test/OpenMP/generic_loop_messages.cpp index 01838a921330..89ede5f9f681 100644 --- a/clang/test/OpenMP/generic_loop_messages.cpp +++ b/clang/test/OpenMP/generic_loop_messages.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -Wuninitialized %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -verify -fopenmp \ +// RUN: -fopenmp-version=51 -Wuninitialized %s void foo() { @@ -6,7 +7,7 @@ void foo() int z; // expected-error@+2 {{statement after '#pragma omp loop' must be a for loop}} - #pragma omp loop + #pragma omp loop bind(thread) i = 0; // OpenMP 5.1 [2.22 Nesting of regions] @@ -15,7 +16,7 @@ void foo() // task, taskloop, critical, ordered, atomic, or masked region. // expected-error@+3 {{region cannot be closely nested inside 'loop' region}} - #pragma omp loop + #pragma omp loop bind(thread) for (i=0; i<1000; ++i) { #pragma omp barrier } @@ -24,7 +25,7 @@ void foo() // atomic, task, or taskloop region. // expected-error@+3 {{region cannot be closely nested inside 'loop' region}} - #pragma omp loop + #pragma omp loop bind(thread) for (i=0; i<1000; ++i) { #pragma omp masked filter(2) { } @@ -35,37 +36,56 @@ void foo() // inside a critical, ordered, loop, atomic, task, or taskloop region. // expected-error@+3 {{region cannot be closely nested inside 'loop' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} - #pragma omp loop + #pragma omp loop bind(thread) for (i=0; i<1000; ++i) { #pragma omp ordered { } } // expected-error@+3 {{region cannot be closely nested inside 'loop' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} - #pragma omp loop + #pragma omp loop bind(thread) for (i=0; i<1000; ++i) { #pragma omp ordered threads { } } // expected-error@+3 {{region cannot be closely nested inside 'loop' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} - #pragma omp loop + #pragma omp loop bind(thread) for (i=0; i<1000; ++i) { #pragma omp ordered depend(source) } - // bind clause (not yet implemented) + // bind clause + + // expected-error@+1 {{directive '#pragma omp loop' cannot contain more than one 'bind' clause}} + #pragma omp loop bind(thread) bind(thread) + for (i=0; i<1000; ++i) { + } + + // expected-error@+2 {{expected 'teams', 'parallel' or 'thread' in OpenMP clause 'bind'}} + #pragma omp parallel + #pragma omp loop bind(other) + for (i=0; i<1000; ++i) { + } + + #pragma omp target + { + // expected-error@+1 {{region cannot be closely nested inside 'target' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}} + #pragma omp loop bind(teams) + for (i=0; i<10; ++i) { + } + } // collapse clause // expected-error@+4 {{expected 2 for loops after '#pragma omp loop', but found only 1}} // expected-note@+1 {{as specified in 'collapse' clause}} - #pragma omp loop collapse(2) + #pragma omp loop collapse(2) bind(thread) for (i=0; i<1000; ++i) z = i+11; // expected-error@+1 {{directive '#pragma omp loop' cannot contain more than one 'collapse' clause}} - #pragma omp loop collapse(2) collapse(2) + #pragma omp loop collapse(2) collapse(2) bind(thread) for (i=0; i<1000; ++i) for (j=0; j<1000; ++j) z = i+j+11; @@ -73,14 +93,14 @@ void foo() // order clause // expected-error@+1 {{expected 'concurrent' in OpenMP clause 'order'}} - #pragma omp loop order(foo) + #pragma omp loop order(foo) bind(thread) for (i=0; i<1000; ++i) z = i+11; // private clause // expected-error@+1 {{use of undeclared identifier 'undef_var'}} - #pragma omp loop private(undef_var) + #pragma omp loop private(undef_var) bind(thread) for (i=0; i<1000; ++i) z = i+11; @@ -90,13 +110,13 @@ void foo() // iteration variable of a loop that is associated with the construct. // expected-error@+1 {{only loop iteration variables are allowed in 'lastprivate' clause in 'omp loop' directives}} - #pragma omp loop lastprivate(z) + #pragma omp loop lastprivate(z) bind(thread) for (i=0; i<1000; ++i) { z = i+11; } // expected-error@+1 {{only loop iteration variables are allowed in 'lastprivate' clause in 'omp loop' directives}} - #pragma omp loop lastprivate(k) collapse(2) + #pragma omp loop lastprivate(k) collapse(2) bind(thread) for (i=0; i<1000; ++i) for (j=0; j<1000; ++j) for (k=0; k<1000; ++k) @@ -105,7 +125,7 @@ void foo() // reduction // expected-error@+1 {{use of undeclared identifier 'undef_var'}} - #pragma omp loop reduction(+:undef_var) + #pragma omp loop reduction(+:undef_var) bind(thread) for (i=0; i<1000; ++i) z = i+11; } @@ -116,12 +136,12 @@ void templ_test(T t) { // expected-error@+4 {{expected 2 for loops after '#pragma omp loop', but found only 1}} // expected-note@+1 {{as specified in 'collapse' clause}} - #pragma omp loop collapse(C) + #pragma omp loop collapse(C) bind(thread) for (i=0; i<1000; ++i) z = i+11; // expected-error@+1 {{only loop iteration variables are allowed in 'lastprivate' clause in 'omp loop' directives}} - #pragma omp loop lastprivate(z) + #pragma omp loop lastprivate(z) bind(thread) for (i=0; i<1000; ++i) { z = i+11; } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index fb5c3fa9390a..0b953b2dd686 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2581,6 +2581,8 @@ void OMPClauseEnqueue::VisitOMPAffinityClause(const OMPAffinityClause *C) { for (const Expr *E : C->varlists()) Visitor->AddStmt(E); } +void OMPClauseEnqueue::VisitOMPBindClause(const OMPBindClause *C) {} + } // namespace void EnqueueVisitor::EnqueueChildren(const OMPClause *S) { diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 919853792944..5a06cce48174 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1480,6 +1480,7 @@ CHECK_SIMPLE_CLAUSE(When, OMPC_when) CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args) CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args) CHECK_SIMPLE_CLAUSE(MemoryOrder, OMPC_memory_order) +CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind) CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize) CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 7ef0614c9f99..211573132bac 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -365,6 +365,10 @@ def OMPC_Filter : Clause<"filter"> { } def OMPC_When: Clause<"when"> {} +def OMPC_Bind : Clause<"bind"> { + let clangClass = "OMPBindClause"; +} + //===----------------------------------------------------------------------===// // Definition of OpenMP directives //===----------------------------------------------------------------------===// @@ -1739,6 +1743,7 @@ def OMP_loop : Directive<"loop"> { VersionedClause<OMPC_Reduction>, ]; let allowedOnceClauses = [ + VersionedClause<OMPC_Bind, 50>, VersionedClause<OMPC_Collapse>, VersionedClause<OMPC_Order>, ]; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits