[flang][OpenMP] Enhance parser support for atomic construct to OpenMP 5.0

Summary:
This patch enhances parser support for atomic construct to OpenMP 5.0.
2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
                 ATOMIC [clause]
       clause -> memory-order-clause | HINT(hint-expression)
       memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED
       atomic-clause -> READ | WRITE | UPDATE | CAPTURE

The patch includes code changes and testcase modifications.

Reviewed By: DavidTruby, kiranchandramohan, sameeranjoshi

Differential Revision: https://reviews.llvm.org/D82931
This commit is contained in:
Kiran Kumar T P 2020-09-08 06:52:07 +05:30
parent 35f708a3c9
commit 4536c6acb3
6 changed files with 159 additions and 81 deletions

View File

@ -344,6 +344,8 @@
ATOMIC [seq_cst]
atomic-clause -> READ | WRITE | UPDATE | CAPTURE
2.13.6 end-atomic -> END ATOMIC
2.13.7 flush -> FLUSH [(variable-name-list)]
2.13.8 ordered -> ORDERED ordered-construct-clause [[[,] ordered-construct-clause]...]

View File

@ -445,6 +445,9 @@ public:
NODE(parser, OmpAtomicCapture)
NODE(OmpAtomicCapture, Stmt1)
NODE(OmpAtomicCapture, Stmt2)
NODE(parser, OmpAtomicMemoryOrderClause)
NODE(parser, OmpAtomicMemoryOrderClauseList)
NODE(parser, OmpAtomicMemoryOrderClausePostList)
NODE(parser, OmpAtomicRead)
NODE(parser, OmpAtomicUpdate)
NODE(parser, OmpAtomicWrite)
@ -464,7 +467,6 @@ public:
#include "llvm/Frontend/OpenMP/OMP.cpp.inc"
NODE(parser, OmpClauseList)
NODE(parser, OmpCriticalDirective)
NODE(OmpCriticalDirective, Hint)
NODE(parser, OmpDeclareTargetSpecifier)
NODE(parser, OmpDeclareTargetWithClause)
NODE(parser, OmpDeclareTargetWithList)
@ -487,6 +489,7 @@ public:
NODE(parser, OmpEndCriticalDirective)
NODE(parser, OmpEndLoopDirective)
NODE(parser, OmpEndSectionsDirective)
NODE(parser, OmpHintExpr)
NODE(parser, OmpIfClause)
NODE_ENUM(OmpIfClause, DirectiveNameModifier)
NODE(parser, OmpLinearClause)
@ -499,10 +502,12 @@ public:
NODE(parser, OmpMapType)
NODE(OmpMapType, Always)
NODE_ENUM(OmpMapType, Type)
NODE(parser, OmpMemoryClause)
NODE_ENUM(OmpMemoryClause, MemoryOrder)
NODE(parser, OmpMemoryClauseList)
NODE(parser, OmpMemoryClausePostList)
NODE(parser, OmpMemoryOrderClause)
static std::string GetNodeName(const llvm::omp::Clause &x) {
return llvm::Twine(
"llvm::omp::Clause = ", llvm::omp::getOpenMPClauseName(x))
.str();
}
NODE(parser, OmpNowait)
NODE(parser, OmpObject)
NODE(parser, OmpObjectList)
@ -549,7 +554,6 @@ public:
NODE(parser, OpenMPDeclareSimdConstruct)
NODE(parser, OpenMPDeclareTargetConstruct)
NODE(parser, OmpFlushMemoryClause)
NODE_ENUM(OmpFlushMemoryClause, FlushMemoryOrder)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPLoopConstruct)
NODE(parser, OpenMPSimpleStandaloneConstruct)

View File

@ -3591,12 +3591,14 @@ struct OpenMPDeclarativeConstruct {
u;
};
// HINT(hint-expression)
WRAPPER_CLASS(OmpHintExpr, ConstantExpr);
// 2.13.2 CRITICAL [Name] <block> END CRITICAL [Name]
struct OmpCriticalDirective {
TUPLE_CLASS_BOILERPLATE(OmpCriticalDirective);
WRAPPER_CLASS(Hint, ConstantExpr);
CharBlock source;
std::tuple<Verbatim, std::optional<Name>, std::optional<Hint>> t;
std::tuple<Verbatim, std::optional<Name>, std::optional<OmpHintExpr>> t;
};
struct OmpEndCriticalDirective {
TUPLE_CLASS_BOILERPLATE(OmpEndCriticalDirective);
@ -3608,44 +3610,56 @@ struct OpenMPCriticalConstruct {
std::tuple<OmpCriticalDirective, Block, OmpEndCriticalDirective> t;
};
// 2.13.6 atomic -> ATOMIC [seq_cst[,]] atomic-clause [[,]seq_cst] |
// ATOMIC [seq_cst]
// 2.17.7 atomic -> ATOMIC [clause[,]] atomic-clause [[,]clause] |
// ATOMIC [clause]
// clause -> memory-order-clause | HINT(hint-expression)
// memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED
// atomic-clause -> READ | WRITE | UPDATE | CAPTURE
// END ATOMIC
EMPTY_CLASS(OmpEndAtomic);
// ATOMIC Memory related clause
struct OmpMemoryClause {
ENUM_CLASS(MemoryOrder, SeqCst)
WRAPPER_CLASS_BOILERPLATE(OmpMemoryClause, MemoryOrder);
// Memory order clause
struct OmpMemoryOrderClause {
WRAPPER_CLASS_BOILERPLATE(OmpMemoryOrderClause, llvm::omp::Clause);
CharBlock source;
};
WRAPPER_CLASS(OmpMemoryClauseList, std::list<OmpMemoryClause>);
WRAPPER_CLASS(OmpMemoryClausePostList, std::list<OmpMemoryClause>);
// ATOMIC Memory order clause or hint expression
struct OmpAtomicMemoryOrderClause {
UNION_CLASS_BOILERPLATE(OmpAtomicMemoryOrderClause);
std::variant<OmpMemoryOrderClause, OmpHintExpr> u;
};
WRAPPER_CLASS(
OmpAtomicMemoryOrderClauseList, std::list<OmpAtomicMemoryOrderClause>);
WRAPPER_CLASS(
OmpAtomicMemoryOrderClausePostList, std::list<OmpAtomicMemoryOrderClause>);
// ATOMIC READ
struct OmpAtomicRead {
TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList,
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
OmpAtomicMemoryOrderClausePostList, Statement<AssignmentStmt>,
std::optional<OmpEndAtomic>>
t;
};
// ATOMIC WRITE
struct OmpAtomicWrite {
TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList,
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
OmpAtomicMemoryOrderClausePostList, Statement<AssignmentStmt>,
std::optional<OmpEndAtomic>>
t;
};
// ATOMIC UPDATE
struct OmpAtomicUpdate {
TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList,
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
OmpAtomicMemoryOrderClausePostList, Statement<AssignmentStmt>,
std::optional<OmpEndAtomic>>
t;
};
@ -3654,16 +3668,16 @@ struct OmpAtomicCapture {
TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture);
WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
std::tuple<OmpMemoryClauseList, Verbatim, OmpMemoryClausePostList, Stmt1,
Stmt2, OmpEndAtomic>
std::tuple<OmpAtomicMemoryOrderClauseList, Verbatim,
OmpAtomicMemoryOrderClausePostList, Stmt1, Stmt2, OmpEndAtomic>
t;
};
// ATOMIC
struct OmpAtomic {
TUPLE_CLASS_BOILERPLATE(OmpAtomic);
std::tuple<Verbatim, OmpMemoryClauseList, Statement<AssignmentStmt>,
std::optional<OmpEndAtomic>>
std::tuple<Verbatim, OmpAtomicMemoryOrderClauseList,
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
t;
};
@ -3707,8 +3721,7 @@ struct OpenMPCancelConstruct {
// release
// acquire
struct OmpFlushMemoryClause {
ENUM_CLASS(FlushMemoryOrder, AcqRel, Release, Acquire)
WRAPPER_CLASS_BOILERPLATE(OmpFlushMemoryClause, FlushMemoryOrder);
WRAPPER_CLASS_BOILERPLATE(OmpFlushMemoryClause, llvm::omp::Clause);
CharBlock source;
};

View File

@ -300,9 +300,9 @@ TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
// release
// acquire
TYPE_PARSER(sourced(construct<OmpFlushMemoryClause>(
"ACQ_REL" >> pure(OmpFlushMemoryClause::FlushMemoryOrder::AcqRel) ||
"RELEASE" >> pure(OmpFlushMemoryClause::FlushMemoryOrder::Release) ||
"ACQUIRE" >> pure(OmpFlushMemoryClause::FlushMemoryOrder::Acquire))))
"ACQ_REL" >> pure(llvm::omp::Clause::OMPC_acq_rel) ||
"RELEASE" >> pure(llvm::omp::Clause::OMPC_release) ||
"ACQUIRE" >> pure(llvm::omp::Clause::OMPC_acquire))))
TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
maybe(Parser<OmpFlushMemoryClause>{}),
@ -384,51 +384,74 @@ TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
construct<Call>(Parser<ProcedureDesignator>{},
parenthesized(optionalList(actualArgSpec))))))
// 2.13.6 ATOMIC [seq_cst[,]] atomic-clause [[,]seq_cst] | ATOMIC [seq_cst]
// atomic-clause -> READ | WRITE | UPDATE | CAPTURE
// Hint Expression => HINT(hint-expression)
TYPE_PARSER("HINT" >> construct<OmpHintExpr>(parenthesized(constantExpr)))
// 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
// ATOMIC [clause]
// clause -> memory-order-clause | HINT(hint-expression)
// memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED
// atomic-clause -> READ | WRITE | UPDATE | CAPTURE
// OMP END ATOMIC
TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok))
// ATOMIC Memory related clause
TYPE_PARSER(sourced(construct<OmpMemoryClause>(
"SEQ_CST" >> pure(OmpMemoryClause::MemoryOrder::SeqCst))))
// Memory order clause
TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>(
"SEQ_CST" >> pure(llvm::omp::Clause::OMPC_seq_cst) ||
"ACQ_REL" >> pure(llvm::omp::Clause::OMPC_acq_rel) ||
"RELEASE" >> pure(llvm::omp::Clause::OMPC_release) ||
"ACQUIRE" >> pure(llvm::omp::Clause::OMPC_acquire) ||
"RELAXED" >> pure(llvm::omp::Clause::OMPC_relaxed))))
// ATOMIC Memory Clause List
TYPE_PARSER(construct<OmpMemoryClauseList>(
many(maybe(","_tok) >> Parser<OmpMemoryClause>{})))
// ATOMIC Memory order clause or Hint expression
TYPE_PARSER(
construct<OmpAtomicMemoryOrderClause>(Parser<OmpMemoryOrderClause>{}) ||
construct<OmpAtomicMemoryOrderClause>(Parser<OmpHintExpr>{}))
TYPE_PARSER(construct<OmpMemoryClausePostList>(
many(maybe(","_tok) >> Parser<OmpMemoryClause>{})))
// ATOMIC Memory order Clause List
TYPE_PARSER(construct<OmpAtomicMemoryOrderClauseList>(
many(maybe(","_tok) >> Parser<OmpAtomicMemoryOrderClause>{})))
// OMP [SEQ_CST] ATOMIC READ [SEQ_CST]
TYPE_PARSER(construct<OmpAtomicMemoryOrderClausePostList>(
many(maybe(","_tok) >> Parser<OmpAtomicMemoryOrderClause>{})))
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER("ATOMIC" >>
construct<OmpAtomicRead>(Parser<OmpMemoryClauseList>{} / maybe(","_tok),
verbatim("READ"_tok), Parser<OmpMemoryClausePostList>{} / endOmpLine,
construct<OmpAtomicRead>(
Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
verbatim("READ"_tok),
Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
// OMP ATOMIC [SEQ_CST] CAPTURE [SEQ_CST]
TYPE_PARSER("ATOMIC" >>
construct<OmpAtomicCapture>(Parser<OmpMemoryClauseList>{} / maybe(","_tok),
verbatim("CAPTURE"_tok), Parser<OmpMemoryClausePostList>{} / endOmpLine,
statement(assignmentStmt), statement(assignmentStmt),
Parser<OmpEndAtomic>{} / endOmpLine))
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER(
"ATOMIC" >> construct<OmpAtomicCapture>(
Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
verbatim("CAPTURE"_tok),
Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
statement(assignmentStmt), statement(assignmentStmt),
Parser<OmpEndAtomic>{} / endOmpLine))
// OMP ATOMIC [SEQ_CST] UPDATE [SEQ_CST]
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER("ATOMIC" >>
construct<OmpAtomicUpdate>(Parser<OmpMemoryClauseList>{} / maybe(","_tok),
verbatim("UPDATE"_tok), Parser<OmpMemoryClausePostList>{} / endOmpLine,
construct<OmpAtomicUpdate>(
Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
verbatim("UPDATE"_tok),
Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
// OMP ATOMIC [SEQ_CST]
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER(construct<OmpAtomic>(verbatim("ATOMIC"_tok),
Parser<OmpMemoryClauseList>{} / endOmpLine, statement(assignmentStmt),
maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
Parser<OmpAtomicMemoryOrderClauseList>{} / endOmpLine,
statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
// ATOMIC [SEQ_CST] WRITE [SEQ_CST]
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST]
TYPE_PARSER("ATOMIC" >>
construct<OmpAtomicWrite>(Parser<OmpMemoryClauseList>{} / maybe(","_tok),
verbatim("WRITE"_tok), Parser<OmpMemoryClausePostList>{} / endOmpLine,
construct<OmpAtomicWrite>(
Parser<OmpAtomicMemoryOrderClauseList>{} / maybe(","_tok),
verbatim("WRITE"_tok),
Parser<OmpAtomicMemoryOrderClausePostList>{} / endOmpLine,
statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
// Atomic Construct
@ -444,9 +467,7 @@ TYPE_PARSER(startOmpLine >>
verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) /
endOmpLine)
TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok),
maybe(parenthesized(name)),
maybe("HINT" >> construct<OmpCriticalDirective::Hint>(
parenthesized(constantExpr))))) /
maybe(parenthesized(name)), maybe(Parser<OmpHintExpr>{}))) /
endOmpLine)
TYPE_PARSER(construct<OpenMPCriticalConstruct>(

View File

@ -2222,19 +2222,36 @@ public:
break;
}
}
void Unparse(const OmpMemoryClause &x) {
void Unparse(const OmpHintExpr &x) { Word("HINT("), Walk(x.v), Put(')'); }
void Unparse(const OmpMemoryOrderClause &x) {
switch (x.v) {
case OmpMemoryClause::MemoryOrder::SeqCst:
case llvm::omp::Clause::OMPC_seq_cst:
Word("SEQ_CST");
break;
case llvm::omp::Clause::OMPC_acq_rel:
Word("ACQ_REL");
break;
case llvm::omp::Clause::OMPC_release:
Word("RELEASE");
break;
case llvm::omp::Clause::OMPC_acquire:
Word("ACQUIRE");
break;
case llvm::omp::Clause::OMPC_relaxed:
Word("RELAXED");
break;
default:
break;
}
}
void Unparse(const OmpMemoryClauseList &x) { Walk(" ", x.v, " "); }
void Unparse(const OmpMemoryClausePostList &x) { Walk(" ", x.v, " "); }
void Unparse(const OmpAtomicMemoryOrderClauseList &x) { Walk(" ", x.v, " "); }
void Unparse(const OmpAtomicMemoryOrderClausePostList &x) {
Walk(" ", x.v, " ");
}
void Unparse(const OmpAtomic &x) {
BeginOpenMP();
Word("!$OMP ATOMIC");
Walk(std::get<OmpMemoryClauseList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<Statement<AssignmentStmt>>(x.t));
@ -2245,9 +2262,9 @@ public:
void Unparse(const OmpAtomicCapture &x) {
BeginOpenMP();
Word("!$OMP ATOMIC");
Walk(std::get<OmpMemoryClauseList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
Word(" CAPTURE");
Walk(std::get<OmpMemoryClausePostList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<OmpAtomicCapture::Stmt1>(x.t));
@ -2260,9 +2277,9 @@ public:
void Unparse(const OmpAtomicRead &x) {
BeginOpenMP();
Word("!$OMP ATOMIC");
Walk(std::get<OmpMemoryClauseList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
Word(" READ");
Walk(std::get<OmpMemoryClausePostList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<Statement<AssignmentStmt>>(x.t));
@ -2273,9 +2290,9 @@ public:
void Unparse(const OmpAtomicUpdate &x) {
BeginOpenMP();
Word("!$OMP ATOMIC");
Walk(std::get<OmpMemoryClauseList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
Word(" UPDATE");
Walk(std::get<OmpMemoryClausePostList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<Statement<AssignmentStmt>>(x.t));
@ -2286,9 +2303,9 @@ public:
void Unparse(const OmpAtomicWrite &x) {
BeginOpenMP();
Word("!$OMP ATOMIC");
Walk(std::get<OmpMemoryClauseList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClauseList>(x.t));
Word(" WRITE");
Walk(std::get<OmpMemoryClausePostList>(x.t));
Walk(std::get<OmpAtomicMemoryOrderClausePostList>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<Statement<AssignmentStmt>>(x.t));
@ -2300,8 +2317,7 @@ public:
BeginOpenMP();
Word("!$OMP CRITICAL");
Walk(" (", std::get<std::optional<Name>>(x.t), ")");
Walk(" HINT(", std::get<std::optional<OmpCriticalDirective::Hint>>(x.t),
")");
Walk(std::get<std::optional<OmpHintExpr>>(x.t));
Put("\n");
EndOpenMP();
}
@ -2431,15 +2447,17 @@ public:
}
void Unparse(const OmpFlushMemoryClause &x) {
switch (x.v) {
case OmpFlushMemoryClause::FlushMemoryOrder::AcqRel:
case llvm::omp::Clause::OMPC_acq_rel:
Word("ACQ_REL ");
break;
case OmpFlushMemoryClause::FlushMemoryOrder::Release:
case llvm::omp::Clause::OMPC_release:
Word("RELEASE ");
break;
case OmpFlushMemoryClause::FlushMemoryOrder::Acquire:
case llvm::omp::Clause::OMPC_acquire:
Word("ACQUIRE ");
break;
default:
break;
}
}
void Unparse(const OpenMPFlushConstruct &x) {

View File

@ -1,5 +1,5 @@
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
use omp_lib
! Check OpenMP 2.13.6 atomic Construct
a = 1.0
@ -11,12 +11,32 @@
a = b
!$omp end atomic
!$omp atomic read acquire hint(OMP_LOCK_HINT_CONTENDED)
a = b
!$omp atomic release hint(OMP_LOCK_HINT_UNCONTENDED) write
a = b
!$omp atomic capture seq_cst
b = a
a = a + 1
!$omp end atomic
!$omp atomic hint(1) acq_rel capture
b = a
a = a + 1
!$omp end atomic
!ERROR: expected end of line
!ERROR: expected end of line
!$omp atomic read write
a = a + 1
!$omp atomic
a = a + 1
!$omp atomic relaxed
a = a + 1
!$omp end parallel
end