forked from OSchip/llvm-project
[OPENMP] parsing of clause 'safelen' (for directive 'omp simd')
llvm-svn: 204428
This commit is contained in:
parent
db55b02e1c
commit
62c87d2509
|
@ -2367,6 +2367,13 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
bool DataRecursiveASTVisitor<Derived>::VisitOMPSafelenClause(
|
||||||
|
OMPSafelenClause *C) {
|
||||||
|
TraverseStmt(C->getSafelen());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
bool DataRecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
bool DataRecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -250,6 +250,62 @@ public:
|
||||||
StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); }
|
StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief This represents 'safelen' clause in the '#pragma omp ...'
|
||||||
|
/// directive.
|
||||||
|
///
|
||||||
|
/// \code
|
||||||
|
/// #pragma omp simd safelen(4)
|
||||||
|
/// \endcode
|
||||||
|
/// In this example directive '#pragma omp simd' has clause 'safelen'
|
||||||
|
/// with single expression '4'.
|
||||||
|
/// If the safelen clause is used then no two iterations executed
|
||||||
|
/// concurrently with SIMD instructions can have a greater distance
|
||||||
|
/// in the logical iteration space than its value. The parameter of
|
||||||
|
/// the safelen clause must be a constant positive integer expression.
|
||||||
|
///
|
||||||
|
class OMPSafelenClause : public OMPClause {
|
||||||
|
friend class OMPClauseReader;
|
||||||
|
/// \brief Location of '('.
|
||||||
|
SourceLocation LParenLoc;
|
||||||
|
/// \brief Safe iteration space distance.
|
||||||
|
Stmt *Safelen;
|
||||||
|
|
||||||
|
/// \brief Set safelen.
|
||||||
|
void setSafelen(Expr *Len) { Safelen = Len; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// \brief Build 'safelen' clause.
|
||||||
|
///
|
||||||
|
/// \param Len Expression associated with this clause.
|
||||||
|
/// \param StartLoc Starting location of the clause.
|
||||||
|
/// \param EndLoc Ending location of the clause.
|
||||||
|
///
|
||||||
|
OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||||
|
SourceLocation EndLoc)
|
||||||
|
: OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||||
|
Safelen(Len) {}
|
||||||
|
|
||||||
|
/// \brief Build an empty clause.
|
||||||
|
///
|
||||||
|
explicit OMPSafelenClause()
|
||||||
|
: OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()),
|
||||||
|
LParenLoc(SourceLocation()), Safelen(0) {}
|
||||||
|
|
||||||
|
/// \brief Sets the location of '('.
|
||||||
|
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||||
|
/// \brief Returns the location of '('.
|
||||||
|
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||||
|
|
||||||
|
/// \brief Return safe iteration space distance.
|
||||||
|
Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); }
|
||||||
|
|
||||||
|
static bool classof(const OMPClause *T) {
|
||||||
|
return T->getClauseKind() == OMPC_safelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); }
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
|
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
|
||||||
///
|
///
|
||||||
/// \code
|
/// \code
|
||||||
|
|
|
@ -2405,6 +2405,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
|
||||||
|
TraverseStmt(C->getSafelen());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -37,12 +37,13 @@ OPENMP_DIRECTIVE(simd)
|
||||||
// OpenMP clauses.
|
// OpenMP clauses.
|
||||||
OPENMP_CLAUSE(if, OMPIfClause)
|
OPENMP_CLAUSE(if, OMPIfClause)
|
||||||
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
|
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
|
||||||
|
OPENMP_CLAUSE(safelen, OMPSafelenClause)
|
||||||
OPENMP_CLAUSE(default, OMPDefaultClause)
|
OPENMP_CLAUSE(default, OMPDefaultClause)
|
||||||
OPENMP_CLAUSE(private, OMPPrivateClause)
|
OPENMP_CLAUSE(private, OMPPrivateClause)
|
||||||
OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
|
OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
|
||||||
OPENMP_CLAUSE(shared, OMPSharedClause)
|
OPENMP_CLAUSE(shared, OMPSharedClause)
|
||||||
|
|
||||||
// Clauses allowed for OpenMP directives.
|
// Clauses allowed for OpenMP directive 'parallel'.
|
||||||
OPENMP_PARALLEL_CLAUSE(if)
|
OPENMP_PARALLEL_CLAUSE(if)
|
||||||
OPENMP_PARALLEL_CLAUSE(num_threads)
|
OPENMP_PARALLEL_CLAUSE(num_threads)
|
||||||
OPENMP_PARALLEL_CLAUSE(default)
|
OPENMP_PARALLEL_CLAUSE(default)
|
||||||
|
@ -52,6 +53,7 @@ OPENMP_PARALLEL_CLAUSE(shared)
|
||||||
|
|
||||||
// FIXME: more clauses allowed for directive 'omp simd'.
|
// FIXME: more clauses allowed for directive 'omp simd'.
|
||||||
OPENMP_SIMD_CLAUSE(private)
|
OPENMP_SIMD_CLAUSE(private)
|
||||||
|
OPENMP_SIMD_CLAUSE(safelen)
|
||||||
|
|
||||||
// Static attributes for 'default' clause.
|
// Static attributes for 'default' clause.
|
||||||
OPENMP_DEFAULT_KIND(none)
|
OPENMP_DEFAULT_KIND(none)
|
||||||
|
|
|
@ -7114,6 +7114,8 @@ private:
|
||||||
void InitDataSharingAttributesStack();
|
void InitDataSharingAttributesStack();
|
||||||
void DestroyDataSharingAttributesStack();
|
void DestroyDataSharingAttributesStack();
|
||||||
ExprResult PerformImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op);
|
ExprResult PerformImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op);
|
||||||
|
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op,
|
||||||
|
OpenMPClauseKind CKind);
|
||||||
public:
|
public:
|
||||||
/// \brief Called on start of new data sharing attribute block.
|
/// \brief Called on start of new data sharing attribute block.
|
||||||
void StartOpenMPDSABlock(OpenMPDirectiveKind K,
|
void StartOpenMPDSABlock(OpenMPDirectiveKind K,
|
||||||
|
@ -7169,6 +7171,11 @@ public:
|
||||||
SourceLocation StartLoc,
|
SourceLocation StartLoc,
|
||||||
SourceLocation LParenLoc,
|
SourceLocation LParenLoc,
|
||||||
SourceLocation EndLoc);
|
SourceLocation EndLoc);
|
||||||
|
/// \brief Called on well-formed 'safelen' clause.
|
||||||
|
OMPClause *ActOnOpenMPSafelenClause(Expr *Length,
|
||||||
|
SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc,
|
||||||
|
SourceLocation EndLoc);
|
||||||
|
|
||||||
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
||||||
unsigned Argument,
|
unsigned Argument,
|
||||||
|
|
|
@ -613,6 +613,12 @@ void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
|
||||||
OS << ")";
|
OS << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
|
||||||
|
OS << "safelen(";
|
||||||
|
Node->getSafelen()->printPretty(OS, 0, Policy, 0);
|
||||||
|
OS << ")";
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
|
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
|
||||||
OS << "default("
|
OS << "default("
|
||||||
<< getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
|
<< getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
|
||||||
|
|
|
@ -274,6 +274,11 @@ void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
|
||||||
Profiler->VisitStmt(C->getNumThreads());
|
Profiler->VisitStmt(C->getNumThreads());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) {
|
||||||
|
if (C->getSafelen())
|
||||||
|
Profiler->VisitStmt(C->getSafelen());
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -79,6 +79,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
||||||
case OMPC_threadprivate:
|
case OMPC_threadprivate:
|
||||||
case OMPC_if:
|
case OMPC_if:
|
||||||
case OMPC_num_threads:
|
case OMPC_num_threads:
|
||||||
|
case OMPC_safelen:
|
||||||
case OMPC_private:
|
case OMPC_private:
|
||||||
case OMPC_firstprivate:
|
case OMPC_firstprivate:
|
||||||
case OMPC_shared:
|
case OMPC_shared:
|
||||||
|
@ -104,6 +105,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
||||||
case OMPC_threadprivate:
|
case OMPC_threadprivate:
|
||||||
case OMPC_if:
|
case OMPC_if:
|
||||||
case OMPC_num_threads:
|
case OMPC_num_threads:
|
||||||
|
case OMPC_safelen:
|
||||||
case OMPC_private:
|
case OMPC_private:
|
||||||
case OMPC_firstprivate:
|
case OMPC_firstprivate:
|
||||||
case OMPC_shared:
|
case OMPC_shared:
|
||||||
|
|
|
@ -257,7 +257,8 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
||||||
/// \brief Parsing of OpenMP clauses.
|
/// \brief Parsing of OpenMP clauses.
|
||||||
///
|
///
|
||||||
/// clause:
|
/// clause:
|
||||||
/// default-clause|private-clause|firstprivate-clause|shared-clause
|
/// if-clause | num_threads-clause | safelen-clause | default-clause |
|
||||||
|
/// private-clause | firstprivate-clause | shared-clause
|
||||||
///
|
///
|
||||||
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||||
OpenMPClauseKind CKind, bool FirstClause) {
|
OpenMPClauseKind CKind, bool FirstClause) {
|
||||||
|
@ -273,9 +274,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||||
switch (CKind) {
|
switch (CKind) {
|
||||||
case OMPC_if:
|
case OMPC_if:
|
||||||
case OMPC_num_threads:
|
case OMPC_num_threads:
|
||||||
|
case OMPC_safelen:
|
||||||
// OpenMP [2.5, Restrictions]
|
// OpenMP [2.5, Restrictions]
|
||||||
// At most one if clause can appear on the directive.
|
// At most one if clause can appear on the directive.
|
||||||
// At most one num_threads clause can appear on the directive.
|
// At most one num_threads clause can appear on the directive.
|
||||||
|
// OpenMP [2.8.1, simd construct, Restrictions]
|
||||||
|
// Only one safelen clause can appear on a simd directive.
|
||||||
if (!FirstClause) {
|
if (!FirstClause) {
|
||||||
Diag(Tok, diag::err_omp_more_one_clause)
|
Diag(Tok, diag::err_omp_more_one_clause)
|
||||||
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
|
||||||
|
@ -321,6 +325,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||||
/// if-clause:
|
/// if-clause:
|
||||||
/// 'if' '(' expression ')'
|
/// 'if' '(' expression ')'
|
||||||
///
|
///
|
||||||
|
/// num_threads-clause:
|
||||||
|
/// 'num_threads' '(' expression ')'
|
||||||
|
///
|
||||||
|
/// safelen-clause:
|
||||||
|
/// 'safelen' '(' expression ')'
|
||||||
|
///
|
||||||
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
|
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
|
||||||
SourceLocation Loc = ConsumeToken();
|
SourceLocation Loc = ConsumeToken();
|
||||||
|
|
||||||
|
|
|
@ -761,6 +761,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
||||||
case OMPC_num_threads:
|
case OMPC_num_threads:
|
||||||
Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
|
Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
|
||||||
break;
|
break;
|
||||||
|
case OMPC_safelen:
|
||||||
|
Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
|
||||||
|
break;
|
||||||
case OMPC_default:
|
case OMPC_default:
|
||||||
case OMPC_private:
|
case OMPC_private:
|
||||||
case OMPC_firstprivate:
|
case OMPC_firstprivate:
|
||||||
|
@ -868,6 +871,38 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
|
||||||
EndLoc);
|
EndLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
|
||||||
|
OpenMPClauseKind CKind) {
|
||||||
|
if (!E)
|
||||||
|
return ExprError();
|
||||||
|
if (E->isValueDependent() || E->isTypeDependent() ||
|
||||||
|
E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
|
||||||
|
return Owned(E);
|
||||||
|
llvm::APSInt Result;
|
||||||
|
ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
|
||||||
|
if (ICE.isInvalid())
|
||||||
|
return ExprError();
|
||||||
|
if (!Result.isStrictlyPositive()) {
|
||||||
|
Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
|
||||||
|
<< getOpenMPClauseName(CKind) << E->getSourceRange();
|
||||||
|
return ExprError();
|
||||||
|
}
|
||||||
|
return ICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc,
|
||||||
|
SourceLocation EndLoc) {
|
||||||
|
// OpenMP [2.8.1, simd construct, Description]
|
||||||
|
// The parameter of the safelen clause must be a constant
|
||||||
|
// positive integer expression.
|
||||||
|
ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
|
||||||
|
if (Safelen.isInvalid())
|
||||||
|
return 0;
|
||||||
|
return new (Context)
|
||||||
|
OMPSafelenClause(Safelen.take(), StartLoc, LParenLoc, EndLoc);
|
||||||
|
}
|
||||||
|
|
||||||
OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
||||||
unsigned Argument,
|
unsigned Argument,
|
||||||
SourceLocation ArgumentLoc,
|
SourceLocation ArgumentLoc,
|
||||||
|
@ -883,6 +918,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
||||||
break;
|
break;
|
||||||
case OMPC_if:
|
case OMPC_if:
|
||||||
case OMPC_num_threads:
|
case OMPC_num_threads:
|
||||||
|
case OMPC_safelen:
|
||||||
case OMPC_private:
|
case OMPC_private:
|
||||||
case OMPC_firstprivate:
|
case OMPC_firstprivate:
|
||||||
case OMPC_shared:
|
case OMPC_shared:
|
||||||
|
@ -956,6 +992,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
||||||
break;
|
break;
|
||||||
case OMPC_if:
|
case OMPC_if:
|
||||||
case OMPC_num_threads:
|
case OMPC_num_threads:
|
||||||
|
case OMPC_safelen:
|
||||||
case OMPC_default:
|
case OMPC_default:
|
||||||
case OMPC_threadprivate:
|
case OMPC_threadprivate:
|
||||||
case OMPC_unknown:
|
case OMPC_unknown:
|
||||||
|
|
|
@ -1323,6 +1323,16 @@ public:
|
||||||
LParenLoc, EndLoc);
|
LParenLoc, EndLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Build a new OpenMP 'safelen' clause.
|
||||||
|
///
|
||||||
|
/// By default, performs semantic analysis to build the new statement.
|
||||||
|
/// Subclasses may override this routine to provide different behavior.
|
||||||
|
OMPClause *RebuildOMPSafelenClause(Expr *Len, SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc,
|
||||||
|
SourceLocation EndLoc) {
|
||||||
|
return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Build a new OpenMP 'default' clause.
|
/// \brief Build a new OpenMP 'default' clause.
|
||||||
///
|
///
|
||||||
/// By default, performs semantic analysis to build the new statement.
|
/// By default, performs semantic analysis to build the new statement.
|
||||||
|
@ -6340,6 +6350,16 @@ TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
||||||
C->getLocEnd());
|
C->getLocEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
OMPClause *
|
||||||
|
TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
|
||||||
|
ExprResult E = getDerived().TransformExpr(C->getSafelen());
|
||||||
|
if (E.isInvalid())
|
||||||
|
return 0;
|
||||||
|
return getDerived().RebuildOMPSafelenClause(
|
||||||
|
E.take(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
OMPClause *
|
OMPClause *
|
||||||
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
|
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
|
||||||
|
|
|
@ -1677,6 +1677,9 @@ OMPClause *OMPClauseReader::readClause() {
|
||||||
case OMPC_num_threads:
|
case OMPC_num_threads:
|
||||||
C = new (Context) OMPNumThreadsClause();
|
C = new (Context) OMPNumThreadsClause();
|
||||||
break;
|
break;
|
||||||
|
case OMPC_safelen:
|
||||||
|
C = new (Context) OMPSafelenClause();
|
||||||
|
break;
|
||||||
case OMPC_default:
|
case OMPC_default:
|
||||||
C = new (Context) OMPDefaultClause();
|
C = new (Context) OMPDefaultClause();
|
||||||
break;
|
break;
|
||||||
|
@ -1707,6 +1710,11 @@ void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
||||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) {
|
||||||
|
C->setSafelen(Reader->Reader.ReadSubExpr());
|
||||||
|
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||||
C->setDefaultKind(
|
C->setDefaultKind(
|
||||||
static_cast<OpenMPDefaultClauseKind>(Record[Idx++]));
|
static_cast<OpenMPDefaultClauseKind>(Record[Idx++]));
|
||||||
|
|
|
@ -1684,6 +1684,11 @@ void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
||||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {
|
||||||
|
Writer->Writer.AddStmt(C->getSafelen());
|
||||||
|
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||||
Record.push_back(C->getDefaultKind());
|
Record.push_back(C->getDefaultKind());
|
||||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||||
|
|
|
@ -33,12 +33,22 @@ template<class T> struct S {
|
||||||
T val;
|
T val;
|
||||||
// CHECK: T res;
|
// CHECK: T res;
|
||||||
// CHECK: T val;
|
// CHECK: T val;
|
||||||
#pragma omp simd private(val)
|
#pragma omp simd private(val) safelen(7)
|
||||||
// CHECK-NEXT: #pragma omp simd private(val)
|
// CHECK-NEXT: #pragma omp simd private(val) safelen(7)
|
||||||
for (T i = 7; i < m_a; ++i) {
|
for (T i = 7; i < m_a; ++i) {
|
||||||
val = v[i-7] + m_a;
|
val = v[i-7] + m_a;
|
||||||
res = val;
|
res = val;
|
||||||
}
|
}
|
||||||
|
const T clen = 3;
|
||||||
|
// CHECK: T clen = 3;
|
||||||
|
#pragma omp simd safelen(clen-1)
|
||||||
|
// CHECK-NEXT: #pragma omp simd safelen(clen - 1)
|
||||||
|
for(T i = clen+2; i < 20; ++i) {
|
||||||
|
// CHECK-NEXT: for (T i = clen + 2; i < 20; ++i) {
|
||||||
|
v[i] = v[v-clen] + 1;
|
||||||
|
// CHECK-NEXT: v[i] = v[v - clen] + 1;
|
||||||
|
}
|
||||||
|
// CHECK-NEXT: }
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
~S()
|
~S()
|
||||||
|
@ -46,6 +56,24 @@ template<class T> struct S {
|
||||||
T m_a;
|
T m_a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<int LEN> struct S2 {
|
||||||
|
static void func(int n, float *a, float *b, float *c) {
|
||||||
|
#pragma omp simd safelen(LEN)
|
||||||
|
for(int i = 0; i < n; i++) {
|
||||||
|
c[i] = a[i] + b[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// S2<4>::func is called below in main.
|
||||||
|
// CHECK: template <int LEN = 4> struct S2 {
|
||||||
|
// CHECK-NEXT: static void func(int n, float *a, float *b, float *c) {
|
||||||
|
// CHECK-NEXT: #pragma omp simd safelen(4)
|
||||||
|
// CHECK-NEXT: for (int i = 0; i < n; i++) {
|
||||||
|
// CHECK-NEXT: c[i] = a[i] + b[i];
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
int b = argc, c, d, e, f, g;
|
int b = argc, c, d, e, f, g;
|
||||||
int k1=0,k2=0;
|
int k1=0,k2=0;
|
||||||
|
@ -69,11 +97,16 @@ int main (int argc, char **argv) {
|
||||||
for (int i = 0; i < 10; ++i)foo();
|
for (int i = 0; i < 10; ++i)foo();
|
||||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||||
// CHECK-NEXT: foo();
|
// CHECK-NEXT: foo();
|
||||||
#pragma omp simd
|
const int CLEN = 4;
|
||||||
// CHECK-NEXT: #pragma omp simd
|
// CHECK-NEXT: const int CLEN = 4;
|
||||||
|
#pragma omp simd safelen(CLEN)
|
||||||
|
// CHECK-NEXT: #pragma omp simd safelen(CLEN)
|
||||||
for (int i = 0; i < 10; ++i)foo();
|
for (int i = 0; i < 10; ++i)foo();
|
||||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||||
// CHECK-NEXT: foo();
|
// CHECK-NEXT: foo();
|
||||||
|
|
||||||
|
float arr[16];
|
||||||
|
S2<4>::func(0,arr,arr,arr);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,75 @@ void test_non_identifiers()
|
||||||
for (i = 0; i < 16; ++i) ;
|
for (i = 0; i < 16; ++i) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int foo();
|
||||||
|
void test_safelen()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
// expected-error@+1 {{expected '('}}
|
||||||
|
#pragma omp simd safelen
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+1 {{expected expression}}
|
||||||
|
#pragma omp simd safelen()
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(,
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(,)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-warning@+2 {{extra tokens at the end of '#pragma omp simd' are ignored}}
|
||||||
|
// expected-error@+1 {{expected '('}}
|
||||||
|
#pragma omp simd safelen 4)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+2 {{expected ')'}}
|
||||||
|
// expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(4
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+2 {{expected ')'}}
|
||||||
|
// expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(4,
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+2 {{expected ')'}}
|
||||||
|
// expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(4,)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// xxpected-error@+1 {{expected expression}}
|
||||||
|
#pragma omp simd safelen(4)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+2 {{expected ')'}}
|
||||||
|
// expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(4 4)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+2 {{expected ')'}}
|
||||||
|
// expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(4,,4)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
#pragma omp simd safelen(4)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+2 {{expected ')'}}
|
||||||
|
// expected-note@+1 {{to match this '('}}
|
||||||
|
#pragma omp simd safelen(4,8)
|
||||||
|
for (i = 0; i < 16; ++i) ;
|
||||||
|
// expected-error@+1 {{expression is not an integer constant expression}}
|
||||||
|
#pragma omp simd safelen(2.5)
|
||||||
|
for (i = 0; i < 16; ++i);
|
||||||
|
// expected-error@+1 {{expression is not an integer constant expression}}
|
||||||
|
#pragma omp simd safelen(foo())
|
||||||
|
for (i = 0; i < 16; ++i);
|
||||||
|
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
|
||||||
|
#pragma omp simd safelen(-5)
|
||||||
|
for (i = 0; i < 16; ++i);
|
||||||
|
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
|
||||||
|
#pragma omp simd safelen(0)
|
||||||
|
for (i = 0; i < 16; ++i);
|
||||||
|
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
|
||||||
|
#pragma omp simd safelen(5-5)
|
||||||
|
for (i = 0; i < 16; ++i);
|
||||||
|
}
|
||||||
|
|
||||||
void test_private()
|
void test_private()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -121,3 +190,4 @@ void test_firstprivate()
|
||||||
#pragma omp simd firstprivate(
|
#pragma omp simd firstprivate(
|
||||||
for (i = 0; i < 16; ++i) ;
|
for (i = 0; i < 16; ++i) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
// 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) { //expected-note 2 {{declared here}}
|
||||||
|
#pragma omp simd safelen // expected-error {{expected '(' after 'safelen'}}
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
#pragma omp simd safelen ( // expected-error {{expected expression}} 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 simd safelen () // expected-error {{expected expression}}
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
|
||||||
|
// expected-error@+2 2 {{expression is not an integral constant expression}}
|
||||||
|
// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
|
||||||
|
#pragma omp simd safelen (argc
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
|
||||||
|
#pragma omp simd safelen (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 simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}}
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
#pragma omp simd safelen ((ST > 0) ? 1 + ST : 2)
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
// expected-error@+3 2 {{directive '#pragma omp simd' cannot contain more than one 'safelen' clause}}
|
||||||
|
// expected-error@+2 2 {{argument to 'safelen' clause must be a positive integer value}}
|
||||||
|
// expected-error@+1 2 {{expression is not an integral constant expression}}
|
||||||
|
#pragma omp simd safelen (foobool(argc)), safelen (true), safelen (-5)
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
#pragma omp simd safelen (S) // expected-error {{'S' does not refer to a value}}
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
// expected-error@+1 2 {{expression is not an integral constant expression}}
|
||||||
|
#pragma omp simd safelen (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 simd safelen (4)
|
||||||
|
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
|
||||||
|
#pragma omp simd safelen (N) // expected-error {{argument to 'safelen' 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 simd safelen // expected-error {{expected '(' after 'safelen'}}
|
||||||
|
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||||
|
#pragma omp simd safelen ( // expected-error {{expected expression}} 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 simd safelen () // expected-error {{expected expression}}
|
||||||
|
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||||
|
#pragma omp simd safelen (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 simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}}
|
||||||
|
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||||
|
#pragma omp simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
|
||||||
|
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||||
|
// expected-error@+3 {{expression is not an integral constant expression}}
|
||||||
|
// expected-error@+2 2 {{directive '#pragma omp simd' cannot contain more than one 'safelen' clause}}
|
||||||
|
// expected-error@+1 2 {{argument to 'safelen' clause must be a positive integer value}}
|
||||||
|
#pragma omp simd safelen (foobool(argc)), safelen (true), safelen (-5)
|
||||||
|
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||||
|
#pragma omp simd safelen (S1) // expected-error {{'S1' does not refer to a value}}
|
||||||
|
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
|
||||||
|
// expected-error@+1 {{expression is not an integral constant expression}}
|
||||||
|
#pragma omp simd safelen (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 simd' must be a for loop}}
|
||||||
|
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
|
||||||
|
#pragma omp simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
|
||||||
|
foo();
|
||||||
|
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
|
||||||
|
return tmain<int, char, 12, 4>(argc, argv);
|
||||||
|
}
|
||||||
|
|
|
@ -1932,6 +1932,10 @@ void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
|
||||||
Visitor->AddStmt(C->getNumThreads());
|
Visitor->AddStmt(C->getNumThreads());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) {
|
||||||
|
Visitor->AddStmt(C->getSafelen());
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
Loading…
Reference in New Issue