Skip to content

[flang][OpenMP] Use OmpDirectiveSpecification in standalone directives #131163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 20, 2025
14 changes: 6 additions & 8 deletions flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,16 @@ std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) {
return std::visit(
Fortran::common::visitors{
[&](const OpenMPStandaloneConstruct &c) -> std::string {
return std::visit(
Fortran::common::visitors{
[&](const OpenMPSimpleStandaloneConstruct &d) {
return common::visit(
common::visitors{
[&](const OmpMetadirectiveDirective &d) {
return normalize_construct_name(d.source.ToString());
},
[&](auto &&d) {
const CharBlock &source{
std::get<OmpDirectiveName>(d.v.t).source};
return normalize_construct_name(source.ToString());
},
[&](const auto &c) {
// Get source from the directive or verbatim fields
const CharBlock &source{std::get<0>(c.t).source};
return normalize_construct_name(source.ToString());
},
},
c.u);
},
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ class ParseTreeDumper {
NODE(parser, OmpLocatorList)
NODE(parser, OmpReductionSpecifier)
NODE(parser, OmpArgument)
NODE(parser, OmpArgumentList)
NODE(parser, OmpMetadirectiveDirective)
NODE(parser, OmpMatchClause)
NODE(parser, OmpOtherwiseClause)
Expand Down
23 changes: 12 additions & 11 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3557,6 +3557,11 @@ struct OmpArgument {
OmpMapperSpecifier, OmpReductionSpecifier>
u;
};

struct OmpArgumentList {
WRAPPER_CLASS_BOILERPLATE(OmpArgumentList, std::list<OmpArgument>);
CharBlock source;
};
} // namespace arguments

inline namespace traits {
Expand Down Expand Up @@ -4511,10 +4516,11 @@ struct OmpDirectiveSpecification {
llvm::omp::Directive DirId() const { //
return std::get<OmpDirectiveName>(t).v;
}
const OmpArgumentList &Arguments() const;
const OmpClauseList &Clauses() const;

CharBlock source;
std::tuple<OmpDirectiveName, std::optional<std::list<OmpArgument>>,
std::tuple<OmpDirectiveName, std::optional<OmpArgumentList>,
std::optional<OmpClauseList>, Flags>
t;
};
Expand Down Expand Up @@ -4865,16 +4871,15 @@ struct OmpLoopDirective {

// 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause
struct OpenMPCancellationPointConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct);
WRAPPER_CLASS_BOILERPLATE(
OpenMPCancellationPointConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, OmpClauseList> t;
};

// 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause]
struct OpenMPCancelConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
WRAPPER_CLASS_BOILERPLATE(OpenMPCancelConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, OmpClauseList> t;
};

// Ref: [5.0:254-255], [5.1:287-288], [5.2:322-323]
Expand All @@ -4884,9 +4889,8 @@ struct OpenMPCancelConstruct {
// destroy-clause |
// update-clause
struct OpenMPDepobjConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPDepobjConstruct);
WRAPPER_CLASS_BOILERPLATE(OpenMPDepobjConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, OmpObject, OmpClause> t;
};

// Ref: [5.2: 200-201]
Expand Down Expand Up @@ -4927,11 +4931,8 @@ struct OpenMPDispatchConstruct {
// ACQ_REL | RELEASE | ACQUIRE | // since 5.0
// SEQ_CST // since 5.1
struct OpenMPFlushConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, std::optional<OmpObjectList>,
std::optional<OmpClauseList>, /*TrailingClauses=*/bool>
t;
};

struct OpenMPSimpleStandaloneConstruct {
Expand Down
19 changes: 19 additions & 0 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,25 @@ Object makeObject(const parser::OmpObject &object,
return makeObject(std::get<parser::Designator>(object.u), semaCtx);
}

ObjectList makeObjects(const parser::OmpArgumentList &objects,
semantics::SemanticsContext &semaCtx) {
return makeList(objects.v, [&](const parser::OmpArgument &arg) {
return common::visit(
common::visitors{
[&](const parser::OmpLocator &locator) -> Object {
if (auto *object = std::get_if<parser::OmpObject>(&locator.u)) {
return makeObject(*object, semaCtx);
}
llvm_unreachable("Expecting object");
},
[](auto &&s) -> Object { //
llvm_unreachable("Expecting object");
},
},
arg.u);
});
}

std::optional<Object> getBaseObject(const Object &object,
semantics::SemanticsContext &semaCtx) {
// If it's just the symbol, then there is no base.
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Lower/OpenMP/Clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ inline ObjectList makeObjects(const parser::OmpObjectList &objects,
return makeList(objects.v, makeObjectFn(semaCtx));
}

ObjectList makeObjects(const parser::OmpArgumentList &objects,
semantics::SemanticsContext &semaCtx);

template <typename FuncTy, //
typename ArgTy, //
typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>>
Expand Down
31 changes: 13 additions & 18 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3321,22 +3321,16 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPFlushConstruct &flushConstruct) {
const auto &verbatim = std::get<parser::Verbatim>(flushConstruct.t);
const auto &objectList =
std::get<std::optional<parser::OmpObjectList>>(flushConstruct.t);
const auto &clauseList =
std::get<std::optional<parser::OmpClauseList>>(flushConstruct.t);
ObjectList objects =
objectList ? makeObjects(*objectList, semaCtx) : ObjectList{};
const parser::OpenMPFlushConstruct &construct) {
const auto &argumentList = construct.v.Arguments();
const auto &clauseList = construct.v.Clauses();
ObjectList objects = makeObjects(argumentList, semaCtx);
List<Clause> clauses =
clauseList ? makeList(clauseList->v,
[&](auto &&s) { return makeClause(s, semaCtx); })
: List<Clause>{};
mlir::Location currentLocation = converter.genLocation(verbatim.source);
makeList(clauseList.v, [&](auto &&s) { return makeClause(s, semaCtx); });
mlir::Location currentLocation = converter.genLocation(construct.source);

ConstructQueue queue{buildConstructQueue(
converter.getFirOpBuilder().getModule(), semaCtx, eval, verbatim.source,
converter.getFirOpBuilder().getModule(), semaCtx, eval, construct.source,
llvm::omp::Directive::OMPD_flush, clauses)};
genFlushOp(converter, symTable, semaCtx, eval, currentLocation, objects,
queue, queue.begin());
Expand All @@ -3363,11 +3357,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
const parser::OpenMPDepobjConstruct &construct) {
// These values will be ignored until the construct itself is implemented,
// but run them anyway for the sake of testing (via a Todo test).
auto &ompObj = std::get<parser::OmpObject>(construct.t);
const Object &depObj = makeObject(ompObj, semaCtx);
Clause clause = makeClause(std::get<parser::OmpClause>(construct.t), semaCtx);
(void)depObj;
(void)clause;
ObjectList objects = makeObjects(construct.v.Arguments(), semaCtx);
assert(objects.size() == 1);
List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
assert(clauses.size() == 1);
(void)objects;
(void)clauses;

TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
}
Expand Down
74 changes: 38 additions & 36 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ TYPE_PARSER(sourced( //

TYPE_PARSER(construct<OmpLocatorList>(nonemptyList(Parser<OmpLocator>{})))

TYPE_PARSER(sourced( //
construct<OmpArgumentList>(nonemptyList(Parser<OmpArgument>{}))))

TYPE_PARSER( //
construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{}) ||
construct<OmpTypeSpecifier>(Parser<TypeSpec>{}))
Expand Down Expand Up @@ -1057,9 +1060,9 @@ TYPE_PARSER(sourced(construct<OmpErrorDirective>(

TYPE_PARSER(sourced(construct<OmpDirectiveName>(OmpDirectiveNameParser{})))

OmpDirectiveSpecification static makeFlushFromOldSyntax1(Verbatim &&text,
OmpDirectiveSpecification static makeFlushFromOldSyntax(Verbatim &&text,
std::optional<OmpClauseList> &&clauses,
std::optional<std::list<OmpArgument>> &&args,
std::optional<OmpArgumentList> &&args,
OmpDirectiveSpecification::Flags &&flags) {
return OmpDirectiveSpecification{OmpDirectiveName(text), std::move(args),
std::move(clauses), std::move(flags)};
Expand All @@ -1073,15 +1076,15 @@ TYPE_PARSER(sourced(
// lists absent in the parsed result.
// E.g. for FLUSH(x) SEQ_CST it would find no clauses following
// the directive name, parse the argument list "(x)" and stop.
applyFunction<OmpDirectiveSpecification>(makeFlushFromOldSyntax1,
applyFunction<OmpDirectiveSpecification>(makeFlushFromOldSyntax,
verbatim("FLUSH"_tok) / !lookAhead("("_tok),
maybe(Parser<OmpClauseList>{}),
maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))),
maybe(parenthesized(Parser<OmpArgumentList>{})),
pure(OmpDirectiveSpecification::Flags::DeprecatedSyntax))) ||
// Parse the standard syntax: directive [(arguments)] [clauses]
construct<OmpDirectiveSpecification>( //
sourced(OmpDirectiveNameParser{}),
maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))),
maybe(parenthesized(Parser<OmpArgumentList>{})),
maybe(Parser<OmpClauseList>{}),
pure(OmpDirectiveSpecification::Flags::None))))

Expand Down Expand Up @@ -1157,14 +1160,6 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{})))

// 2.14.2 Cancellation Point construct
TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
verbatim("CANCELLATION POINT"_tok), Parser<OmpClauseList>{})))

// 2.14.1 Cancel construct
TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(
verbatim("CANCEL"_tok), Parser<OmpClauseList>{})))

TYPE_PARSER(sourced(construct<OmpFailClause>(
parenthesized(indirect(Parser<OmpMemoryOrderClause>{})))))

Expand Down Expand Up @@ -1205,29 +1200,6 @@ TYPE_PARSER(sourced(construct<OmpAtomicClause>(
TYPE_PARSER(sourced(construct<OmpAtomicClauseList>(
many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{})))))

TYPE_PARSER(sourced(construct<OpenMPDepobjConstruct>(verbatim("DEPOBJ"_tok),
parenthesized(Parser<OmpObject>{}), sourced(Parser<OmpClause>{}))))

static OpenMPFlushConstruct makeFlushFromOldSyntax(Verbatim &&text,
std::optional<OmpClauseList> &&clauses,
std::optional<OmpObjectList> &&objects) {
bool oldSyntax{
clauses && !clauses->v.empty() && objects && !objects->v.empty()};
return OpenMPFlushConstruct{std::move(text), std::move(objects),
std::move(clauses),
/*TrailingClauses=*/!oldSyntax};
}

TYPE_PARSER(sourced( //
construct<OpenMPFlushConstruct>( //
applyFunction<OpenMPFlushConstruct>(makeFlushFromOldSyntax,
verbatim("FLUSH"_tok), maybe(Parser<OmpClauseList>{}),
maybe(parenthesized(Parser<OmpObjectList>{})))) ||

construct<OpenMPFlushConstruct>( //
verbatim("FLUSH"_tok), maybe(parenthesized(Parser<OmpObjectList>{})),
Parser<OmpClauseList>{}, pure(/*TrailingClauses=*/true))))

static bool IsSimpleStandalone(const OmpDirectiveName &name) {
switch (name.v) {
case llvm::omp::Directive::OMPD_barrier:
Expand All @@ -1249,6 +1221,36 @@ TYPE_PARSER(sourced( //
predicated(OmpDirectiveNameParser{}, IsSimpleStandalone) >=
Parser<OmpDirectiveSpecification>{})))

static inline constexpr auto IsDirective(llvm::omp::Directive dir) {
return [dir](const OmpDirectiveName &name) -> bool { return dir == name.v; };
}

TYPE_PARSER(sourced( //
construct<OpenMPFlushConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_flush)) >=
Parser<OmpDirectiveSpecification>{})))

// 2.14.2 Cancellation Point construct
TYPE_PARSER(sourced( //
construct<OpenMPCancellationPointConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_cancellation_point)) >=
Parser<OmpDirectiveSpecification>{})))

// 2.14.1 Cancel construct
TYPE_PARSER(sourced( //
construct<OpenMPCancelConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_cancel)) >=
Parser<OmpDirectiveSpecification>{})))

TYPE_PARSER(sourced( //
construct<OpenMPDepobjConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_depobj)) >=
Parser<OmpDirectiveSpecification>{})))

// Standalone Constructs
TYPE_PARSER(
sourced( //
Expand Down
8 changes: 8 additions & 0 deletions flang/lib/Parser/parse-tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@ llvm::omp::Clause OmpClause::Id() const {
return std::visit([](auto &&s) { return getClauseIdForClass(s); }, u);
}

const OmpArgumentList &OmpDirectiveSpecification::Arguments() const {
static OmpArgumentList empty{decltype(OmpArgumentList::v){}};
if (auto &arguments = std::get<std::optional<OmpArgumentList>>(t)) {
return *arguments;
}
return empty;
}

const OmpClauseList &OmpDirectiveSpecification::Clauses() const {
static OmpClauseList empty{decltype(OmpClauseList::v){}};
if (auto &clauses = std::get<std::optional<OmpClauseList>>(t)) {
Expand Down
31 changes: 15 additions & 16 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,8 @@ class UnparseVisitor {
}

// OpenMP Clauses & Directives
void Unparse(const OmpArgumentList &x) { Walk(x.v, ", "); }

void Unparse(const OmpTypeNameList &x) { //
Walk(x.v, ",");
}
Expand All @@ -2095,8 +2097,7 @@ class UnparseVisitor {
}
void Unparse(const OmpDirectiveSpecification &x) {
auto unparseArgs{[&]() {
using ArgList = std::list<parser::OmpArgument>;
if (auto &args{std::get<std::optional<ArgList>>(x.t)}) {
if (auto &args{std::get<std::optional<OmpArgumentList>>(x.t)}) {
Put("(");
Walk(*args);
Put(")");
Expand Down Expand Up @@ -2823,15 +2824,15 @@ class UnparseVisitor {
}
void Unparse(const OpenMPCancellationPointConstruct &x) {
BeginOpenMP();
Word("!$OMP CANCELLATION POINT ");
Walk(std::get<OmpClauseList>(x.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPCancelConstruct &x) {
BeginOpenMP();
Word("!$OMP CANCEL ");
Walk(std::get<OmpClauseList>(x.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
Expand All @@ -2858,23 +2859,21 @@ class UnparseVisitor {
}
void Unparse(const OpenMPDepobjConstruct &x) {
BeginOpenMP();
Word("!$OMP DEPOBJ");
Put("(");
Walk(std::get<OmpObject>(x.t));
Put(") ");
Walk(std::get<OmpClause>(x.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPFlushConstruct &x) {
BeginOpenMP();
Word("!$OMP FLUSH");
if (std::get</*ClausesTrailing=*/bool>(x.t)) {
Walk("(", std::get<std::optional<OmpObjectList>>(x.t), ")");
Walk(" ", std::get<std::optional<OmpClauseList>>(x.t));
using Flags = OmpDirectiveSpecification::Flags;
if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) {
Walk("(", std::get<std::optional<OmpArgumentList>>(x.v.t), ")");
Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t));
} else {
Walk(" ", std::get<std::optional<OmpClauseList>>(x.t));
Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")");
Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t));
Walk(" (", std::get<std::optional<OmpArgumentList>>(x.v.t), ")");
}
Put("\n");
EndOpenMP();
Expand Down
Loading