OpenMP 5.0 adds support for the "requires" directive. This patch adds parser support for it in flang.
Differential revision: https://reviews.llvm.org/D136867
* declare target
* threadprivate
* declare reduction
+* requires
There is a parser node for each of these directives and
the parser node saves information associated with the directive,
NODE(parser, OmpMemoryOrderClause)
NODE(parser, OmpAtomicClause)
NODE(parser, OmpAtomicClauseList)
+ NODE(parser, OmpAtomicDefaultMemOrderClause)
+ NODE_ENUM(OmpAtomicDefaultMemOrderClause, Type)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPLoopConstruct)
NODE(parser, OpenMPExecutableAllocate)
+ NODE(parser, OpenMPRequiresConstruct)
NODE(parser, OpenMPSimpleStandaloneConstruct)
NODE(parser, OpenMPStandaloneConstruct)
NODE(parser, OpenMPSectionConstruct)
std::variant<Source, Sink, InOut> u;
};
+// OMP 5.0 2.4 atomic-default-mem-order-clause ->
+// ATOMIC_DEFAULT_MEM_ORDER (SEQ_CST | ACQ_REL |
+// RELAXED)
+struct OmpAtomicDefaultMemOrderClause {
+ ENUM_CLASS(Type, SeqCst, AcqRel, Relaxed)
+ WRAPPER_CLASS_BOILERPLATE(OmpAtomicDefaultMemOrderClause, Type);
+};
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
std::tuple<Verbatim, std::optional<Name>, OmpClauseList> t;
};
+// 2.4 requires -> REQUIRES requires-clause[ [ [,] requires-clause]...]
+struct OpenMPRequiresConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenMPRequiresConstruct);
+ CharBlock source;
+ std::tuple<Verbatim, OmpClauseList> t;
+};
+
// 2.15.2 threadprivate -> THREADPRIVATE (variable-name-list)
struct OpenMPThreadprivate {
TUPLE_CLASS_BOILERPLATE(OpenMPThreadprivate);
CharBlock source;
std::variant<OpenMPDeclarativeAllocate, OpenMPDeclareReductionConstruct,
OpenMPDeclareSimdConstruct, OpenMPDeclareTargetConstruct,
- OpenMPThreadprivate>
+ OpenMPThreadprivate, OpenMPRequiresConstruct>
u;
};
TODO(converter.getCurrentLocation(),
"OpenMPDeclareTargetConstruct");
},
+ [&](const Fortran::parser::OpenMPRequiresConstruct
+ &requiresConstruct) {
+ TODO(converter.getCurrentLocation(), "OpenMPRequiresConstruct");
+ },
[&](const Fortran::parser::OpenMPThreadprivate &threadprivate) {
// The directive is lowered when instantiating the variable to
// support the case of threadprivate variable declared in module.
parenthesized(Parser<OmpAllocateClause>{}))) ||
"ALLOCATOR" >> construct<OmpClause>(construct<OmpClause::Allocator>(
parenthesized(scalarIntExpr))) ||
+ "ATOMIC_DEFAULT_MEM_ORDER" >>
+ construct<OmpClause>(construct<OmpClause::AtomicDefaultMemOrder>(
+ parenthesized(Parser<OmpAtomicDefaultMemOrderClause>{}))) ||
"COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>(
parenthesized(scalarIntConstantExpr))) ||
"COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>(
"DIST_SCHEDULE" >>
construct<OmpClause>(construct<OmpClause::DistSchedule>(
parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) ||
+ "DYNAMIC_ALLOCATORS" >>
+ construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
parenthesized(scalarLogicalExpr))) ||
"FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
parenthesized(Parser<OmpReductionClause>{}))) ||
"RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) ||
"RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
+ "REVERSE_OFFLOAD" >>
+ construct<OmpClause>(construct<OmpClause::ReverseOffload>()) ||
"SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>(
parenthesized(scalarIntConstantExpr))) ||
"SCHEDULE" >> construct<OmpClause>(construct<OmpClause::Schedule>(
parenthesized(Parser<OmpObjectList>{}))) ||
"USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
parenthesized(nonemptyList(name)))) ||
+ "UNIFIED_ADDRESS" >>
+ construct<OmpClause>(construct<OmpClause::UnifiedAddress>()) ||
+ "UNIFIED_SHARED_MEMORY" >>
+ construct<OmpClause>(construct<OmpClause::UnifiedSharedMemory>()) ||
"UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>(
parenthesized(nonemptyList(name)))) ||
"UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()))
"ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
"RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>())))))
+// 2.4 Requires construct [OpenMP 5.0]
+// atomic-default-mem-order-clause ->
+// seq_cst
+// acq_rel
+// relaxed
+TYPE_PARSER(construct<OmpAtomicDefaultMemOrderClause>(
+ "SEQ_CST" >> pure(OmpAtomicDefaultMemOrderClause::Type::SeqCst) ||
+ "ACQ_REL" >> pure(OmpAtomicDefaultMemOrderClause::Type::AcqRel) ||
+ "RELAXED" >> pure(OmpAtomicDefaultMemOrderClause::Type::Relaxed)))
+
// 2.17.7 Atomic construct
// atomic-clause -> memory-order-clause | HINT(hint-expression)
TYPE_PARSER(sourced(construct<OmpAtomicClause>(
sourced(construct<OpenMPDeclareSimdConstruct>(verbatim("DECLARE SIMD"_tok),
maybe(parenthesized(name)), Parser<OmpClauseList>{})))
+// 2.4 Requires construct
+TYPE_PARSER(sourced(construct<OpenMPRequiresConstruct>(
+ verbatim("REQUIRES"_tok), some(Parser<OmpClause>{} / maybe(","_tok)))))
+
// 2.15.2 Threadprivate directive
TYPE_PARSER(sourced(construct<OpenMPThreadprivate>(
verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{}))))
Parser<OpenMPDeclareTargetConstruct>{}) ||
construct<OpenMPDeclarativeConstruct>(
Parser<OpenMPDeclarativeAllocate>{}) ||
+ construct<OpenMPDeclarativeConstruct>(
+ Parser<OpenMPRequiresConstruct>{}) ||
construct<OpenMPDeclarativeConstruct>(Parser<OpenMPThreadprivate>{})) /
endOmpLine)
break;
}
}
+
+ void Unparse(const OmpAtomicDefaultMemOrderClause &x) {
+ switch (x.v) {
+ case OmpAtomicDefaultMemOrderClause::Type::SeqCst:
+ Word("SEQ_CST");
+ break;
+ case OmpAtomicDefaultMemOrderClause::Type::AcqRel:
+ Word("ACQ_REL");
+ break;
+ case OmpAtomicDefaultMemOrderClause::Type::Relaxed:
+ Word("RELAXED");
+ break;
+ }
+ }
+
void Unparse(const OmpAtomicClauseList &x) { Walk(" ", x.v, " "); }
void Unparse(const OmpAtomic &x) {
Word("DECLARE TARGET ");
return true;
},
+ [&](const OpenMPRequiresConstruct &y) {
+ Word("REQUIRES ");
+ Walk(std::get<OmpClauseList>(y.t));
+ Put("\n");
+ EndOpenMP();
+ return false;
+ },
[&](const OpenMPThreadprivate &) {
Word("THREADPRIVATE (");
return true;
dirContext_.pop_back();
}
+void OmpStructureChecker::Enter(const parser::OpenMPRequiresConstruct &x) {
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_requires);
+}
+
+void OmpStructureChecker::Leave(const parser::OpenMPRequiresConstruct &) {
+ dirContext_.pop_back();
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) {
isPredefinedAllocator = true;
const auto &dir{std::get<parser::Verbatim>(x.t)};
void Leave(const parser::OpenMPDeclareTargetConstruct &);
void Enter(const parser::OpenMPExecutableAllocate &);
void Leave(const parser::OpenMPExecutableAllocate &);
+ void Enter(const parser::OpenMPRequiresConstruct &);
+ void Leave(const parser::OpenMPRequiresConstruct &);
void Enter(const parser::OpenMPThreadprivate &);
void Leave(const parser::OpenMPThreadprivate &);
return true;
}
void Post(const parser::OpenMPDeclareSimdConstruct &) { PopContext(); }
+
+ bool Pre(const parser::OpenMPRequiresConstruct &x) {
+ PushContext(x.source, llvm::omp::Directive::OMPD_requires);
+ return true;
+ }
+ void Post(const parser::OpenMPRequiresConstruct &) { PopContext(); }
+
bool Pre(const parser::OpenMPThreadprivate &);
void Post(const parser::OpenMPThreadprivate &) { PopContext(); }
!TODO: all internal errors
! enable declare-reduction example after name resolution
+! 2.4 requires
+
+subroutine requires_1(a)
+ real(8), intent(inout) :: a
+ !$omp requires reverse_offload, unified_shared_memory, atomic_default_mem_order(relaxed)
+ a = a + 0.01
+end subroutine requires_1
+
+subroutine requires_2(a)
+ real(8), intent(inout) :: a
+ !$omp requires unified_address
+ a = a + 0.01
+end subroutine requires_2
+
! 2.8.2 declare-simd
subroutine declare_simd_1(a, b)
}
def OMPC_AtomicDefaultMemOrder : Clause<"atomic_default_mem_order"> {
let clangClass = "OMPAtomicDefaultMemOrderClause";
+ let flangClass = "OmpAtomicDefaultMemOrderClause";
}
def OMPC_Allocate : Clause<"allocate"> {
let clangClass = "OMPAllocateClause";
];
}
def OMP_Requires : Directive<"requires"> {
- let allowedClauses = [
+ let allowedOnceClauses = [
VersionedClause<OMPC_UnifiedAddress>,
VersionedClause<OMPC_UnifiedSharedMemory>,
// OpenMP 5.2 Spec: If an implementation is not supporting a requirement