forked from OSchip/llvm-project
Add OpenMP dist_schedule clause to distribute directive and related regression tests.
llvm-svn: 257917
This commit is contained in:
parent
47f2452da8
commit
b4adf55e0f
clang
include/clang
lib
AST
Basic
CodeGen
Parse
Sema
Serialization
test/OpenMP
tools/libclang
|
@ -3193,6 +3193,135 @@ public:
|
|||
child_range children() { return child_range(&Hint, &Hint + 1); }
|
||||
};
|
||||
|
||||
/// \brief This represents 'dist_schedule' clause in the '#pragma omp ...'
|
||||
/// directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp distribute dist_schedule(static, 3)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp distribute' has 'dist_schedule'
|
||||
/// clause with arguments 'static' and '3'.
|
||||
///
|
||||
class OMPDistScheduleClause : public OMPClause {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
/// \brief A kind of the 'schedule' clause.
|
||||
OpenMPDistScheduleClauseKind Kind;
|
||||
/// \brief Start location of the schedule kind in source code.
|
||||
SourceLocation KindLoc;
|
||||
/// \brief Location of ',' (if any).
|
||||
SourceLocation CommaLoc;
|
||||
/// \brief Chunk size and a reference to pseudo variable for combined
|
||||
/// directives.
|
||||
enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS };
|
||||
Stmt *ChunkSizes[NUM_EXPRS];
|
||||
|
||||
/// \brief Set schedule kind.
|
||||
///
|
||||
/// \param K Schedule kind.
|
||||
///
|
||||
void setDistScheduleKind(OpenMPDistScheduleClauseKind 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 setDistScheduleKindLoc(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) { ChunkSizes[CHUNK_SIZE] = E; }
|
||||
/// \brief Set helper chunk size.
|
||||
///
|
||||
/// \param E Helper chunk size.
|
||||
///
|
||||
void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; }
|
||||
|
||||
public:
|
||||
/// \brief Build 'dist_schedule' clause with schedule kind \a Kind and chunk
|
||||
/// size expression \a ChunkSize.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param KLoc Starting location of the argument.
|
||||
/// \param CommaLoc Location of ','.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param Kind DistSchedule kind.
|
||||
/// \param ChunkSize Chunk size.
|
||||
/// \param HelperChunkSize Helper chunk size for combined directives.
|
||||
///
|
||||
OMPDistScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation KLoc, SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc,
|
||||
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
|
||||
Expr *HelperChunkSize)
|
||||
: OMPClause(OMPC_dist_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
|
||||
ChunkSizes[CHUNK_SIZE] = ChunkSize;
|
||||
ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
|
||||
}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
explicit OMPDistScheduleClause()
|
||||
: OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()),
|
||||
Kind(OMPC_DIST_SCHEDULE_unknown) {
|
||||
ChunkSizes[CHUNK_SIZE] = nullptr;
|
||||
ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
|
||||
}
|
||||
|
||||
/// \brief Get kind of the clause.
|
||||
///
|
||||
OpenMPDistScheduleClauseKind getDistScheduleKind() const { return Kind; }
|
||||
/// \brief Get location of '('.
|
||||
///
|
||||
SourceLocation getLParenLoc() { return LParenLoc; }
|
||||
/// \brief Get kind location.
|
||||
///
|
||||
SourceLocation getDistScheduleKindLoc() { return KindLoc; }
|
||||
/// \brief Get location of ','.
|
||||
///
|
||||
SourceLocation getCommaLoc() { return CommaLoc; }
|
||||
/// \brief Get chunk size.
|
||||
///
|
||||
Expr *getChunkSize() {
|
||||
return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
|
||||
}
|
||||
/// \brief Get chunk size.
|
||||
///
|
||||
Expr *getChunkSize() const {
|
||||
return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
|
||||
}
|
||||
/// \brief Get helper chunk size.
|
||||
///
|
||||
Expr *getHelperChunkSize() {
|
||||
return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
|
||||
}
|
||||
/// \brief Get helper chunk size.
|
||||
///
|
||||
Expr *getHelperChunkSize() const {
|
||||
return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_dist_schedule;
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
|
||||
}
|
||||
};
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
|
||||
|
|
|
@ -2781,6 +2781,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPDistScheduleClause(
|
||||
OMPDistScheduleClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getChunkSize()));
|
||||
TRY_TO(TraverseStmt(C->getHelperChunkSize()));
|
||||
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
|
||||
|
|
|
@ -102,6 +102,9 @@
|
|||
#ifndef OPENMP_MAP_KIND
|
||||
#define OPENMP_MAP_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DIST_SCHEDULE_KIND
|
||||
#define OPENMP_DIST_SCHEDULE_KIND(Name)
|
||||
#endif
|
||||
|
||||
// OpenMP directives.
|
||||
OPENMP_DIRECTIVE(threadprivate)
|
||||
|
@ -175,6 +178,7 @@ OPENMP_CLAUSE(grainsize, OMPGrainsizeClause)
|
|||
OPENMP_CLAUSE(nogroup, OMPNogroupClause)
|
||||
OPENMP_CLAUSE(num_tasks, OMPNumTasksClause)
|
||||
OPENMP_CLAUSE(hint, OMPHintClause)
|
||||
OPENMP_CLAUSE(dist_schedule, OMPDistScheduleClause)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel'.
|
||||
OPENMP_PARALLEL_CLAUSE(if)
|
||||
|
@ -418,6 +422,10 @@ OPENMP_DISTRIBUTE_CLAUSE(private)
|
|||
OPENMP_DISTRIBUTE_CLAUSE(firstprivate)
|
||||
OPENMP_DISTRIBUTE_CLAUSE(lastprivate)
|
||||
OPENMP_DISTRIBUTE_CLAUSE(collapse)
|
||||
OPENMP_DISTRIBUTE_CLAUSE(dist_schedule)
|
||||
|
||||
// Static attributes for 'dist_schedule' clause.
|
||||
OPENMP_DIST_SCHEDULE_KIND(static)
|
||||
|
||||
#undef OPENMP_TASKLOOP_SIMD_CLAUSE
|
||||
#undef OPENMP_TASKLOOP_CLAUSE
|
||||
|
@ -449,3 +457,4 @@ OPENMP_DISTRIBUTE_CLAUSE(collapse)
|
|||
#undef OPENMP_FOR_SIMD_CLAUSE
|
||||
#undef OPENMP_MAP_KIND
|
||||
#undef OPENMP_DISTRIBUTE_CLAUSE
|
||||
#undef OPENMP_DIST_SCHEDULE_KIND
|
||||
|
|
|
@ -95,6 +95,13 @@ enum OpenMPMapClauseKind {
|
|||
OMPC_MAP_unknown
|
||||
};
|
||||
|
||||
/// \brief OpenMP attributes for 'dist_schedule' clause.
|
||||
enum OpenMPDistScheduleClauseKind {
|
||||
#define OPENMP_DIST_SCHEDULE_KIND(Name) OMPC_DIST_SCHEDULE_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_DIST_SCHEDULE_unknown
|
||||
};
|
||||
|
||||
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
|
||||
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
|
||||
|
||||
|
|
|
@ -8192,6 +8192,11 @@ public:
|
|||
OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'dist_schedule' clause.
|
||||
OMPClause *ActOnOpenMPDistScheduleClause(
|
||||
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc,
|
||||
SourceLocation CommaLoc, SourceLocation EndLoc);
|
||||
|
||||
/// \brief The kind of conversion being performed.
|
||||
enum CheckedConversionKind {
|
||||
|
|
|
@ -909,6 +909,16 @@ void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
|
|||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
|
||||
OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
|
||||
OMPC_dist_schedule, Node->getDistScheduleKind());
|
||||
if (Node->getChunkSize()) {
|
||||
OS << ", ";
|
||||
Node->getChunkSize()->printPretty(OS, nullptr, Policy);
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -611,6 +611,16 @@ void StmtProfiler::VisitOMPDistributeDirective(
|
|||
VisitOMPLoopDirective(S);
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPDistScheduleClause(
|
||||
const OMPDistScheduleClause *C) {
|
||||
if (C->getChunkSize()) {
|
||||
Profiler->VisitStmt(C->getChunkSize());
|
||||
if (C->getHelperChunkSize()) {
|
||||
Profiler->VisitStmt(C->getChunkSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitExpr(const Expr *S) {
|
||||
VisitStmt(S);
|
||||
}
|
||||
|
|
|
@ -109,6 +109,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
|||
#define OPENMP_MAP_KIND(Name) .Case(#Name, OMPC_MAP_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_MAP_unknown);
|
||||
case OMPC_dist_schedule:
|
||||
return llvm::StringSwitch<OpenMPDistScheduleClauseKind>(Str)
|
||||
#define OPENMP_DIST_SCHEDULE_KIND(Name) .Case(#Name, OMPC_DIST_SCHEDULE_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_DIST_SCHEDULE_unknown);
|
||||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_if:
|
||||
|
@ -219,6 +224,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
|||
break;
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'map' clause type");
|
||||
case OMPC_dist_schedule:
|
||||
switch (Type) {
|
||||
case OMPC_DIST_SCHEDULE_unknown:
|
||||
return "unknown";
|
||||
#define OPENMP_DIST_SCHEDULE_KIND(Name) \
|
||||
case OMPC_DIST_SCHEDULE_##Name: \
|
||||
return #Name;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'dist_schedule' clause type");
|
||||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_if:
|
||||
|
|
|
@ -2525,6 +2525,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
|||
case OMPC_nogroup:
|
||||
case OMPC_num_tasks:
|
||||
case OMPC_hint:
|
||||
case OMPC_dist_schedule:
|
||||
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -494,6 +494,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|||
Clause = ParseOpenMPSimpleClause(CKind);
|
||||
break;
|
||||
case OMPC_schedule:
|
||||
case OMPC_dist_schedule:
|
||||
// OpenMP [2.7.1, Restrictions, p. 3]
|
||||
// Only one schedule clause can appear on a loop directive.
|
||||
if (!FirstClause) {
|
||||
|
@ -744,6 +745,15 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
|
|||
Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
|
||||
Tok.is(tok::comma))
|
||||
DelimLoc = ConsumeAnyToken();
|
||||
} else if (Kind == OMPC_dist_schedule) {
|
||||
Arg.push_back(getOpenMPSimpleClauseType(
|
||||
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
|
||||
KLoc.push_back(Tok.getLocation());
|
||||
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end))
|
||||
ConsumeAnyToken();
|
||||
if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
|
||||
DelimLoc = ConsumeAnyToken();
|
||||
} else {
|
||||
assert(Kind == OMPC_if);
|
||||
KLoc.push_back(Tok.getLocation());
|
||||
|
@ -758,8 +768,9 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
|
|||
}
|
||||
}
|
||||
|
||||
bool NeedAnExpression =
|
||||
(Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if;
|
||||
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
|
||||
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
|
||||
Kind == OMPC_if;
|
||||
if (NeedAnExpression) {
|
||||
SourceLocation ELoc = Tok.getLocation();
|
||||
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
|
||||
|
|
|
@ -5699,6 +5699,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
|||
case OMPC_simd:
|
||||
case OMPC_map:
|
||||
case OMPC_nogroup:
|
||||
case OMPC_dist_schedule:
|
||||
case OMPC_unknown:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
|
@ -5982,6 +5983,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
|
|||
case OMPC_nogroup:
|
||||
case OMPC_num_tasks:
|
||||
case OMPC_hint:
|
||||
case OMPC_dist_schedule:
|
||||
case OMPC_unknown:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
|
@ -6080,6 +6082,11 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
|
|||
Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
|
||||
DelimLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_dist_schedule:
|
||||
Res = ActOnOpenMPDistScheduleClause(
|
||||
static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
|
||||
StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_final:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_safelen:
|
||||
|
@ -6303,6 +6310,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
|
|||
case OMPC_grainsize:
|
||||
case OMPC_num_tasks:
|
||||
case OMPC_hint:
|
||||
case OMPC_dist_schedule:
|
||||
case OMPC_unknown:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
|
@ -6444,6 +6452,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
|
|||
case OMPC_nogroup:
|
||||
case OMPC_num_tasks:
|
||||
case OMPC_hint:
|
||||
case OMPC_dist_schedule:
|
||||
case OMPC_unknown:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
|
@ -8542,3 +8551,55 @@ OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
|
|||
OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPDistScheduleClause(
|
||||
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc) {
|
||||
if (Kind == OMPC_DIST_SCHEDULE_unknown) {
|
||||
std::string Values;
|
||||
Values += "'";
|
||||
Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
|
||||
Values += "'";
|
||||
Diag(KindLoc, diag::err_omp_unexpected_clause_value)
|
||||
<< Values << getOpenMPClauseName(OMPC_dist_schedule);
|
||||
return nullptr;
|
||||
}
|
||||
Expr *ValExpr = ChunkSize;
|
||||
Expr *HelperValExpr = nullptr;
|
||||
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)) {
|
||||
if (Result.isSigned() && !Result.isStrictlyPositive()) {
|
||||
Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
|
||||
<< "dist_schedule" << ChunkSize->getSourceRange();
|
||||
return nullptr;
|
||||
}
|
||||
} else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
|
||||
auto *ImpVar = buildVarDecl(*this, ChunkSize->getExprLoc(),
|
||||
ChunkSize->getType(), ".chunk.");
|
||||
auto *ImpVarRef = buildDeclRefExpr(*this, ImpVar, ChunkSize->getType(),
|
||||
ChunkSize->getExprLoc(),
|
||||
/*RefersToCapture=*/true);
|
||||
HelperValExpr = ImpVarRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new (Context)
|
||||
OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
|
||||
Kind, ValExpr, HelperValExpr);
|
||||
}
|
||||
|
|
|
@ -1734,6 +1734,19 @@ public:
|
|||
return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'dist_schedule' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *
|
||||
RebuildOMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind,
|
||||
Expr *ChunkSize, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation KindLoc,
|
||||
SourceLocation CommaLoc, SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPDistScheduleClause(
|
||||
Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
|
@ -7889,6 +7902,17 @@ OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) {
|
|||
C->getLParenLoc(), C->getLocEnd());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *TreeTransform<Derived>::TransformOMPDistScheduleClause(
|
||||
OMPDistScheduleClause *C) {
|
||||
ExprResult E = getDerived().TransformExpr(C->getChunkSize());
|
||||
if (E.isInvalid())
|
||||
return nullptr;
|
||||
return getDerived().RebuildOMPDistScheduleClause(
|
||||
C->getDistScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
|
||||
C->getDistScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expression transformation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1878,6 +1878,9 @@ OMPClause *OMPClauseReader::readClause() {
|
|||
case OMPC_hint:
|
||||
C = new (Context) OMPHintClause();
|
||||
break;
|
||||
case OMPC_dist_schedule:
|
||||
C = new (Context) OMPDistScheduleClause();
|
||||
break;
|
||||
}
|
||||
Visit(C);
|
||||
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
|
||||
|
@ -2240,6 +2243,16 @@ void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) {
|
|||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
|
||||
C->setDistScheduleKind(
|
||||
static_cast<OpenMPDistScheduleClauseKind>(Record[Idx++]));
|
||||
C->setChunkSize(Reader->Reader.ReadSubExpr());
|
||||
C->setHelperChunkSize(Reader->Reader.ReadSubExpr());
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setDistScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -2037,6 +2037,15 @@ void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {
|
|||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
|
||||
Record.push_back(C->getDistScheduleKind());
|
||||
Writer->Writer.AddStmt(C->getChunkSize());
|
||||
Writer->Writer.AddStmt(C->getHelperChunkSize());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getDistScheduleKindLoc(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
void foo() {}
|
||||
|
||||
template <class T, int N>
|
||||
T tmain(T argc) {
|
||||
T b = argc, c, d, e, f, g;
|
||||
static T a;
|
||||
// CHECK: static T a;
|
||||
#pragma omp distribute dist_schedule(static,10)
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 10)
|
||||
for (int i=0; i < 2; ++i)a=2;
|
||||
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp distribute dist_schedule(static,a)
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, a)
|
||||
for (int i=0; i < 2; ++i)a=2;
|
||||
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp target
|
||||
#pragma omp teams
|
||||
#pragma omp distribute dist_schedule(static,2)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
for (int j = 0; j < 10; ++j)foo();
|
||||
// CHECK-NEXT: #pragma omp target
|
||||
// CHECK-NEXT: #pragma omp teams
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 2)
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
|
||||
// CHECK-NEXT: foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams
|
||||
#pragma omp distribute dist_schedule(static,a)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
for (int j = 0; j < 10; ++j)foo();
|
||||
// CHECK-NEXT: #pragma omp target
|
||||
// CHECK-NEXT: #pragma omp teams
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, a)
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
|
||||
// CHECK-NEXT: foo();
|
||||
for (int i = 0; i < 10; ++i)foo();
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: foo();
|
||||
#pragma omp distribute
|
||||
// CHECK: #pragma omp distribute
|
||||
for (int i = 0; i < 10; ++i)foo();
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: foo();
|
||||
return T();
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
// CHECK: static int a;
|
||||
#pragma omp distribute dist_schedule(static,10)
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 10)
|
||||
for (int i=0; i < 2; ++i)a=2;
|
||||
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp distribute dist_schedule(static,b)
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, b)
|
||||
for (int i=0; i < 2; ++i)a=2;
|
||||
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp target
|
||||
#pragma omp teams
|
||||
#pragma omp distribute dist_schedule(static,2)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
for (int j = 0; j < 10; ++j)foo();
|
||||
// CHECK-NEXT: #pragma omp target
|
||||
// CHECK-NEXT: #pragma omp teams
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, 2)
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
|
||||
// CHECK-NEXT: foo();
|
||||
#pragma omp target
|
||||
#pragma omp teams
|
||||
#pragma omp distribute dist_schedule(static,a)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
for (int j = 0; j < 10; ++j)foo();
|
||||
// CHECK-NEXT: #pragma omp target
|
||||
// CHECK-NEXT: #pragma omp teams
|
||||
// CHECK-NEXT: #pragma omp distribute dist_schedule(static, a)
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
|
||||
// CHECK-NEXT: foo();
|
||||
for (int i = 0; i < 10; ++i)foo();
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: foo();
|
||||
#pragma omp distribute
|
||||
// CHECK: #pragma omp distribute
|
||||
for (int i = 0; i < 10; ++i)foo();
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: foo();
|
||||
return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0]));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}} expected-note {{declared here}}
|
||||
|
||||
template <class T, int N>
|
||||
T tmain(T argc) {
|
||||
T b = argc, c, d, e, f, g;
|
||||
char ** argv;
|
||||
static T a;
|
||||
// CHECK: static T a;
|
||||
#pragma omp distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp distribute' are ignored}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp distribute' cannot contain more than one 'dist_schedule' clause}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
return T();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#pragma omp distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp distribute' are ignored}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp distribute' cannot contain more than one 'dist_schedule' clause}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
#pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i) foo();
|
||||
return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
|
||||
}
|
|
@ -2222,6 +2222,11 @@ void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) {
|
|||
void OMPClauseEnqueue::VisitOMPMapClause(const OMPMapClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPDistScheduleClause(
|
||||
const OMPDistScheduleClause *C) {
|
||||
Visitor->AddStmt(C->getChunkSize());
|
||||
Visitor->AddStmt(C->getHelperChunkSize());
|
||||
}
|
||||
}
|
||||
|
||||
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
|
||||
|
|
Loading…
Reference in New Issue