mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 19:56:06 +00:00
[OPENMP] Initial support for 'schedule' clause.
llvm-svn: 211342
This commit is contained in:
parent
f5e2997aff
commit
56dafe87c2
@ -2343,6 +2343,13 @@ RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
TraverseStmt(C->getChunkSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
template <typename T>
|
||||
void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
|
||||
|
@ -502,6 +502,104 @@ public:
|
||||
StmtRange children() { return StmtRange(); }
|
||||
};
|
||||
|
||||
/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp for schedule(static, 3)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp for' has 'schedule' clause with
|
||||
/// arguments 'static' and '3'.
|
||||
///
|
||||
class OMPScheduleClause : public OMPClause {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
/// \brief A kind of the 'schedule' clause.
|
||||
OpenMPScheduleClauseKind Kind;
|
||||
/// \brief Start location of the schedule ind in source code.
|
||||
SourceLocation KindLoc;
|
||||
/// \brief Location of ',' (if any).
|
||||
SourceLocation CommaLoc;
|
||||
/// \brief Chunk size.
|
||||
Stmt *ChunkSize;
|
||||
|
||||
/// \brief Set schedule kind.
|
||||
///
|
||||
/// \param K Schedule kind.
|
||||
///
|
||||
void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
|
||||
/// \brief Sets the location of '('.
|
||||
///
|
||||
/// \param Loc Location of '('.
|
||||
///
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
/// \brief Set schedule kind start location.
|
||||
///
|
||||
/// \param KLoc Schedule kind location.
|
||||
///
|
||||
void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
|
||||
/// \brief Set location of ','.
|
||||
///
|
||||
/// \param Loc Location of ','.
|
||||
///
|
||||
void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; }
|
||||
/// \brief Set chunk size.
|
||||
///
|
||||
/// \param E Chunk size.
|
||||
///
|
||||
void setChunkSize(Expr *E) { ChunkSize = E; }
|
||||
|
||||
public:
|
||||
/// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size
|
||||
/// expression \a ChunkSize.
|
||||
///
|
||||
/// \brief StartLoc Starting location of the clause.
|
||||
/// \brief LParenLoc Location of '('.
|
||||
/// \brief KLoc Starting location of the argument.
|
||||
/// \brief CommaLoc Location of ','.
|
||||
/// \brief EndLoc Ending location of the clause.
|
||||
/// \brief Kind Schedule kind.
|
||||
/// \brief ChunkSize Chunk size.
|
||||
///
|
||||
OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation KLoc, SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
|
||||
Expr *ChunkSize)
|
||||
: OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) {}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
explicit OMPScheduleClause()
|
||||
: OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()),
|
||||
Kind(OMPC_SCHEDULE_unknown), ChunkSize(nullptr) {}
|
||||
|
||||
/// \brief Get kind of the clause.
|
||||
///
|
||||
OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
|
||||
/// \brief Get location of '('.
|
||||
///
|
||||
SourceLocation getLParenLoc() { return LParenLoc; }
|
||||
/// \brief Get kind location.
|
||||
///
|
||||
SourceLocation getScheduleKindLoc() { return KindLoc; }
|
||||
/// \brief Get location of ','.
|
||||
///
|
||||
SourceLocation getCommaLoc() { return CommaLoc; }
|
||||
/// \brief Get chunk size.
|
||||
///
|
||||
Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSize); }
|
||||
/// \brief Get chunk size.
|
||||
///
|
||||
Expr *getChunkSize() const { return dyn_cast_or_null<Expr>(ChunkSize); }
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_schedule;
|
||||
}
|
||||
|
||||
StmtRange children() { return StmtRange(&ChunkSize, &ChunkSize + 1); }
|
||||
};
|
||||
|
||||
/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
|
||||
///
|
||||
/// \code
|
||||
|
@ -2364,6 +2364,13 @@ RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
TraverseStmt(C->getChunkSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
template <typename T>
|
||||
void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
|
||||
|
@ -33,6 +33,9 @@
|
||||
#ifndef OPENMP_PROC_BIND_KIND
|
||||
# define OPENMP_PROC_BIND_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_SCHEDULE_KIND
|
||||
#define OPENMP_SCHEDULE_KIND(Name)
|
||||
#endif
|
||||
|
||||
// OpenMP directives.
|
||||
OPENMP_DIRECTIVE(threadprivate)
|
||||
@ -56,6 +59,7 @@ OPENMP_CLAUSE(linear, OMPLinearClause)
|
||||
OPENMP_CLAUSE(aligned, OMPAlignedClause)
|
||||
OPENMP_CLAUSE(copyin, OMPCopyinClause)
|
||||
OPENMP_CLAUSE(proc_bind, OMPProcBindClause)
|
||||
OPENMP_CLAUSE(schedule, OMPScheduleClause)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel'.
|
||||
OPENMP_PARALLEL_CLAUSE(if)
|
||||
@ -82,6 +86,7 @@ OPENMP_FOR_CLAUSE(lastprivate)
|
||||
OPENMP_FOR_CLAUSE(firstprivate)
|
||||
OPENMP_FOR_CLAUSE(reduction)
|
||||
OPENMP_FOR_CLAUSE(collapse)
|
||||
OPENMP_FOR_CLAUSE(schedule)
|
||||
|
||||
// Static attributes for 'default' clause.
|
||||
OPENMP_DEFAULT_KIND(none)
|
||||
@ -92,6 +97,14 @@ OPENMP_PROC_BIND_KIND(master)
|
||||
OPENMP_PROC_BIND_KIND(close)
|
||||
OPENMP_PROC_BIND_KIND(spread)
|
||||
|
||||
// Static attributes for 'schedule' clause.
|
||||
OPENMP_SCHEDULE_KIND(static)
|
||||
OPENMP_SCHEDULE_KIND(dynamic)
|
||||
OPENMP_SCHEDULE_KIND(guided)
|
||||
OPENMP_SCHEDULE_KIND(auto)
|
||||
OPENMP_SCHEDULE_KIND(runtime)
|
||||
|
||||
#undef OPENMP_SCHEDULE_KIND
|
||||
#undef OPENMP_PROC_BIND_KIND
|
||||
#undef OPENMP_DEFAULT_KIND
|
||||
#undef OPENMP_DIRECTIVE
|
||||
|
@ -52,6 +52,14 @@ enum OpenMPProcBindClauseKind {
|
||||
OMPC_PROC_BIND_unknown
|
||||
};
|
||||
|
||||
/// \brief OpenMP attributes for 'schedule' clause.
|
||||
enum OpenMPScheduleClauseKind {
|
||||
#define OPENMP_SCHEDULE_KIND(Name) \
|
||||
OMPC_SCHEDULE_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_SCHEDULE_unknown
|
||||
};
|
||||
|
||||
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
|
||||
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
|
||||
|
||||
|
@ -2345,6 +2345,12 @@ private:
|
||||
/// \param Kind Kind of current clause.
|
||||
///
|
||||
OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind);
|
||||
/// \brief Parses clause with a single expression and an additional argument
|
||||
/// of a kind \a Kind.
|
||||
///
|
||||
/// \param Kind Kind of current clause.
|
||||
///
|
||||
OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind);
|
||||
/// \brief Parses clause with the list of variables of a kind \a Kind.
|
||||
///
|
||||
/// \param Kind Kind of current clause.
|
||||
|
@ -7366,6 +7366,21 @@ public:
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
OMPClause *ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
|
||||
unsigned Argument, Expr *Expr,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ArgumentLoc,
|
||||
SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'schedule' clause.
|
||||
OMPClause *ActOnOpenMPScheduleClause(OpenMPScheduleClauseKind Kind,
|
||||
Expr *ChunkSize, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation KindLoc,
|
||||
SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
OMPClause *
|
||||
ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> Vars,
|
||||
Expr *TailExpr, SourceLocation StartLoc,
|
||||
|
@ -628,6 +628,16 @@ void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
|
||||
<< ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
|
||||
OS << "schedule("
|
||||
<< getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
|
||||
if (Node->getChunkSize()) {
|
||||
OS << ", ";
|
||||
Node->getChunkSize()->printPretty(OS, nullptr, Policy);
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
|
||||
for (typename T::varlist_iterator I = Node->varlist_begin(),
|
||||
|
@ -288,6 +288,11 @@ void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||
|
||||
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
|
||||
|
||||
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
|
||||
if (C->getChunkSize())
|
||||
Profiler->VisitStmt(C->getChunkSize());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
|
||||
for (auto *I : Node->varlists())
|
||||
|
@ -76,6 +76,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
||||
#define OPENMP_PROC_BIND_KIND(Name) .Case(#Name, OMPC_PROC_BIND_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_PROC_BIND_unknown);
|
||||
case OMPC_schedule:
|
||||
return llvm::StringSwitch<OpenMPScheduleClauseKind>(Str)
|
||||
#define OPENMP_SCHEDULE_KIND(Name) .Case(#Name, OMPC_SCHEDULE_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_SCHEDULE_unknown);
|
||||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_if:
|
||||
@ -118,6 +123,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'proc_bind' clause type");
|
||||
case OMPC_schedule:
|
||||
switch (Type) {
|
||||
case OMPC_SCHEDULE_unknown:
|
||||
return "unknown";
|
||||
#define OPENMP_SCHEDULE_KIND(Name) \
|
||||
case OMPC_SCHEDULE_##Name: \
|
||||
return #Name;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'schedule' clause type");
|
||||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_if:
|
||||
|
@ -262,7 +262,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
||||
/// if-clause | num_threads-clause | safelen-clause | default-clause |
|
||||
/// private-clause | firstprivate-clause | shared-clause | linear-clause |
|
||||
/// aligned-clause | collapse-clause | lastprivate-clause |
|
||||
/// reduction-clause
|
||||
/// reduction-clause | proc_bind-clause | schedule-clause
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind, bool FirstClause) {
|
||||
@ -307,6 +307,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
|
||||
Clause = ParseOpenMPSimpleClause(CKind);
|
||||
break;
|
||||
case OMPC_schedule:
|
||||
// OpenMP [2.7.1, Restrictions, p. 3]
|
||||
// Only one schedule clause can appear on a loop directive.
|
||||
if (!FirstClause) {
|
||||
Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
|
||||
<< getOpenMPClauseName(CKind);
|
||||
}
|
||||
|
||||
Clause = ParseOpenMPSingleExprWithArgClause(CKind);
|
||||
break;
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_lastprivate:
|
||||
@ -399,6 +409,48 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
|
||||
Tok.getLocation());
|
||||
}
|
||||
|
||||
/// \brief Parsing of OpenMP clauses with single expressions and some additional
|
||||
/// argument like 'schedule' or 'dist_schedule'.
|
||||
///
|
||||
/// schedule-clause:
|
||||
/// 'schedule' '(' kind [',' expression ] ')'
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
|
||||
SourceLocation Loc = ConsumeToken();
|
||||
SourceLocation CommaLoc;
|
||||
// Parse '('.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
||||
getOpenMPClauseName(Kind)))
|
||||
return nullptr;
|
||||
|
||||
ExprResult Val;
|
||||
unsigned Type = getOpenMPSimpleClauseType(
|
||||
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
|
||||
SourceLocation KLoc = Tok.getLocation();
|
||||
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end))
|
||||
ConsumeAnyToken();
|
||||
|
||||
if (Kind == OMPC_schedule &&
|
||||
(Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
|
||||
Type == OMPC_SCHEDULE_guided) &&
|
||||
Tok.is(tok::comma)) {
|
||||
CommaLoc = ConsumeAnyToken();
|
||||
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
|
||||
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
|
||||
if (Val.isInvalid())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Parse ')'.
|
||||
T.consumeClose();
|
||||
|
||||
return Actions.ActOnOpenMPSingleExprWithArgClause(
|
||||
Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
|
||||
T.getCloseLocation());
|
||||
}
|
||||
|
||||
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
|
||||
UnqualifiedId &ReductionId) {
|
||||
SourceLocation TemplateKWLoc;
|
||||
|
@ -1513,6 +1513,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
||||
break;
|
||||
case OMPC_default:
|
||||
case OMPC_proc_bind:
|
||||
case OMPC_schedule:
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_lastprivate:
|
||||
@ -1689,6 +1690,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
|
||||
case OMPC_num_threads:
|
||||
case OMPC_safelen:
|
||||
case OMPC_collapse:
|
||||
case OMPC_schedule:
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_lastprivate:
|
||||
@ -1779,6 +1781,95 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
|
||||
OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
|
||||
OpenMPClauseKind Kind, unsigned Argument, Expr *Expr,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation ArgumentLoc, SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc) {
|
||||
OMPClause *Res = nullptr;
|
||||
switch (Kind) {
|
||||
case OMPC_schedule:
|
||||
Res = ActOnOpenMPScheduleClause(
|
||||
static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc,
|
||||
LParenLoc, ArgumentLoc, CommaLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_safelen:
|
||||
case OMPC_collapse:
|
||||
case OMPC_default:
|
||||
case OMPC_proc_bind:
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_lastprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPScheduleClause(
|
||||
OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc) {
|
||||
if (Kind == OMPC_SCHEDULE_unknown) {
|
||||
std::string Values;
|
||||
std::string Sep(", ");
|
||||
for (unsigned i = 0; i < OMPC_SCHEDULE_unknown; ++i) {
|
||||
Values += "'";
|
||||
Values += getOpenMPSimpleClauseTypeName(OMPC_schedule, i);
|
||||
Values += "'";
|
||||
switch (i) {
|
||||
case OMPC_SCHEDULE_unknown - 2:
|
||||
Values += " or ";
|
||||
break;
|
||||
case OMPC_SCHEDULE_unknown - 1:
|
||||
break;
|
||||
default:
|
||||
Values += Sep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Diag(KindLoc, diag::err_omp_unexpected_clause_value)
|
||||
<< Values << getOpenMPClauseName(OMPC_schedule);
|
||||
return nullptr;
|
||||
}
|
||||
Expr *ValExpr = ChunkSize;
|
||||
if (ChunkSize) {
|
||||
if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
|
||||
!ChunkSize->isInstantiationDependent() &&
|
||||
!ChunkSize->containsUnexpandedParameterPack()) {
|
||||
SourceLocation ChunkSizeLoc = ChunkSize->getLocStart();
|
||||
ExprResult Val =
|
||||
PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
|
||||
if (Val.isInvalid())
|
||||
return nullptr;
|
||||
|
||||
ValExpr = Val.get();
|
||||
|
||||
// OpenMP [2.7.1, Restrictions]
|
||||
// chunk_size must be a loop invariant integer expression with a positive
|
||||
// value.
|
||||
llvm::APSInt Result;
|
||||
if (ValExpr->isIntegerConstantExpr(Result, Context) &&
|
||||
Result.isSigned() && !Result.isStrictlyPositive()) {
|
||||
Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
|
||||
<< "schedule" << ChunkSize->getSourceRange();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc,
|
||||
EndLoc, Kind, ValExpr);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPVarListClause(
|
||||
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
|
||||
@ -1819,6 +1910,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
|
||||
case OMPC_collapse:
|
||||
case OMPC_default:
|
||||
case OMPC_proc_bind:
|
||||
case OMPC_schedule:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
|
@ -1377,6 +1377,21 @@ public:
|
||||
StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'schedule' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPScheduleClause(OpenMPScheduleClauseKind Kind,
|
||||
Expr *ChunkSize,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation KindLoc,
|
||||
SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPScheduleClause(
|
||||
Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'private' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
@ -6472,6 +6487,17 @@ TreeTransform<Derived>::TransformOMPProcBindClause(OMPProcBindClause *C) {
|
||||
C->getLParenLoc(), C->getLocEnd());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) {
|
||||
ExprResult E = getDerived().TransformExpr(C->getChunkSize());
|
||||
if (E.isInvalid())
|
||||
return nullptr;
|
||||
return getDerived().RebuildOMPScheduleClause(
|
||||
C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
|
||||
C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
|
||||
|
@ -1691,6 +1691,9 @@ OMPClause *OMPClauseReader::readClause() {
|
||||
case OMPC_proc_bind:
|
||||
C = new (Context) OMPProcBindClause();
|
||||
break;
|
||||
case OMPC_schedule:
|
||||
C = new (Context) OMPScheduleClause();
|
||||
break;
|
||||
case OMPC_private:
|
||||
C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
@ -1757,6 +1760,15 @@ void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
|
||||
C->setProcBindKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
C->setScheduleKind(
|
||||
static_cast<OpenMPScheduleClauseKind>(Record[Idx++]));
|
||||
C->setChunkSize(Reader->Reader.ReadSubExpr());
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
unsigned NumVars = C->varlist_size();
|
||||
|
@ -1707,6 +1707,14 @@ void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
|
||||
Writer->Writer.AddSourceLocation(C->getProcBindKindKwLoc(), Record);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
Record.push_back(C->getScheduleKind());
|
||||
Writer->Writer.AddStmt(C->getChunkSize());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getScheduleKindLoc(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
|
@ -13,19 +13,19 @@ T tmain(T argc) {
|
||||
T b = argc, c, d, e, f, g;
|
||||
static T a;
|
||||
// CHECK: static T a;
|
||||
#pragma omp for
|
||||
// CHECK-NEXT: #pragma omp for
|
||||
#pragma omp for schedule(dynamic)
|
||||
// CHECK-NEXT: #pragma omp for schedule(dynamic)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
a = 2;
|
||||
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp parallel
|
||||
#pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N)
|
||||
#pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
for (int j = 0; j < 10; ++j)
|
||||
foo();
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N)
|
||||
// CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N)
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
|
||||
// CHECK-NEXT: foo();
|
||||
@ -36,19 +36,19 @@ int main(int argc, char **argv) {
|
||||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
// CHECK: static int a;
|
||||
#pragma omp for
|
||||
// CHECK-NEXT: #pragma omp for
|
||||
#pragma omp for schedule(guided, argc)
|
||||
// CHECK-NEXT: #pragma omp for schedule(guided, argc)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
a = 2;
|
||||
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp parallel
|
||||
#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2)
|
||||
#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
for (int j = 0; j < 10; ++j)
|
||||
foo();
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2)
|
||||
// CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto)
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
|
||||
// CHECK-NEXT: foo();
|
||||
|
91
clang/test/OpenMP/for_schedule_messages.cpp
Normal file
91
clang/test/OpenMP/for_schedule_messages.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}}
|
||||
|
||||
template <class T, typename S, int N, int ST> // expected-note {{declared here}}
|
||||
T tmain(T argc, S **argv) {
|
||||
#pragma omp for schedule // expected-error {{expected '(' after 'schedule'}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (auto // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (auto, // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (runtime, 3) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp for schedule (guided argc
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
// expected-error@+1 2 {{argument to 'schedule' clause must be a positive integer value}}
|
||||
#pragma omp for schedule (static, ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (dynamic, 1)) // expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (guided, (ST > 0) ? 1 + ST : 2)
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
// expected-error@+2 2 {{directive '#pragma omp for' cannot contain more than one 'schedule' clause}}
|
||||
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
|
||||
#pragma omp for schedule (static, foobool(argc)), schedule (dynamic, true), schedule (guided, -5)
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (static, S) // expected-error {{'S' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
// expected-error@+1 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
#pragma omp for schedule (guided, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (dynamic, 1)
|
||||
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
#pragma omp for schedule (static, N) // expected-error {{argument to 'schedule' clause must be a positive integer value}}
|
||||
for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||
return argc;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#pragma omp for schedule // expected-error {{expected '(' after 'schedule'}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule ( // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule () // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (auto // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (auto_dynamic // expected-error {{expected 'static', 'dynamic', 'guided', 'auto' or 'runtime' in OpenMP clause 'schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (auto, // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (runtime, 3) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (guided, 4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (static, 2+2)) // expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (dynamic, foobool(1) > 0 ? 1 : 2)
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
// expected-error@+2 2 {{directive '#pragma omp for' cannot contain more than one 'schedule' clause}}
|
||||
// expected-error@+1 {{argument to 'schedule' clause must be a positive integer value}}
|
||||
#pragma omp for schedule (guided, foobool(argc)), schedule (static, true), schedule (dynamic, -5)
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
#pragma omp for schedule (guided, S1) // expected-error {{'S1' does not refer to a value}} expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
#pragma omp for schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||
// expected-error@+3 {{statement after '#pragma omp for' must be a for loop}}
|
||||
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
|
||||
#pragma omp for schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
|
||||
return tmain<int, char, 1, 0>(argc, argv);
|
||||
}
|
||||
|
@ -1945,6 +1945,10 @@ void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPScheduleClause(const OMPScheduleClause *C) {
|
||||
Visitor->AddStmt(C->getChunkSize());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
|
||||
for (const auto *I : Node->varlists())
|
||||
|
Loading…
x
Reference in New Issue
Block a user