[flang-commits] [flang] 4eac7bc - [OpenMP] Add parsing/sema/serialization for 'bind' clause.
Mike Rice via flang-commits
flang-commits at lists.llvm.org
Thu Nov 4 14:41:01 PDT 2021
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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +4 {{expected 2 for loops after '#pragma omp loop', but found only 1}}
// expected-note at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +4 {{expected 2 for loops after '#pragma omp loop', but found only 1}}
// expected-note at +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 at +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>,
];
More information about the flang-commits
mailing list