forked from OSchip/llvm-project
[OpenMP] Add parsing/sema/serialization for 'bind' clause.
Differential Revision: https://reviews.llvm.org/D113154
This commit is contained in:
parent
5540e27043
commit
4eac7bcf1a
|
@ -8405,6 +8405,96 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// 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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -11424,6 +11424,12 @@ public:
|
|||
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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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'.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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' ')'
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -2256,6 +2256,19 @@ public:
|
|||
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 different 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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>,
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue