Skip to content

[flang][OpenMP] Overhaul implementation of ATOMIC construct #137852

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

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions flang/examples/FeatureList/FeatureList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,13 +445,6 @@ struct NodeVisitor {
READ_FEATURE(ObjectDecl)
READ_FEATURE(OldParameterStmt)
READ_FEATURE(OmpAlignedClause)
READ_FEATURE(OmpAtomic)
READ_FEATURE(OmpAtomicCapture)
READ_FEATURE(OmpAtomicCapture::Stmt1)
READ_FEATURE(OmpAtomicCapture::Stmt2)
READ_FEATURE(OmpAtomicRead)
READ_FEATURE(OmpAtomicUpdate)
READ_FEATURE(OmpAtomicWrite)
READ_FEATURE(OmpBeginBlockDirective)
READ_FEATURE(OmpBeginLoopDirective)
READ_FEATURE(OmpBeginSectionsDirective)
Expand Down Expand Up @@ -480,7 +473,6 @@ struct NodeVisitor {
READ_FEATURE(OmpIterationOffset)
READ_FEATURE(OmpIterationVector)
READ_FEATURE(OmpEndAllocators)
READ_FEATURE(OmpEndAtomic)
READ_FEATURE(OmpEndBlockDirective)
READ_FEATURE(OmpEndCriticalDirective)
READ_FEATURE(OmpEndLoopDirective)
Expand Down Expand Up @@ -566,8 +558,6 @@ struct NodeVisitor {
READ_FEATURE(OpenMPDeclareTargetConstruct)
READ_FEATURE(OmpMemoryOrderType)
READ_FEATURE(OmpMemoryOrderClause)
READ_FEATURE(OmpAtomicClause)
READ_FEATURE(OmpAtomicClauseList)
READ_FEATURE(OmpAtomicDefaultMemOrderClause)
READ_FEATURE(OpenMPFlushConstruct)
READ_FEATURE(OpenMPLoopConstruct)
Expand Down
27 changes: 8 additions & 19 deletions flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,19 @@ SourcePosition OpenMPCounterVisitor::getLocation(const OpenMPConstruct &c) {
// the directive field.
[&](const auto &c) -> SourcePosition {
const CharBlock &source{std::get<0>(c.t).source};
return (parsing->allCooked().GetSourcePositionRange(source))->first;
return parsing->allCooked().GetSourcePositionRange(source)->first;
},
[&](const OpenMPAtomicConstruct &c) -> SourcePosition {
return std::visit(
[&](const auto &o) -> SourcePosition {
const CharBlock &source{std::get<Verbatim>(o.t).source};
return parsing->allCooked()
.GetSourcePositionRange(source)
->first;
},
c.u);
const CharBlock &source{c.source};
return parsing->allCooked().GetSourcePositionRange(source)->first;
},
[&](const OpenMPSectionConstruct &c) -> SourcePosition {
const CharBlock &source{c.source};
return (parsing->allCooked().GetSourcePositionRange(source))->first;
return parsing->allCooked().GetSourcePositionRange(source)->first;
},
[&](const OpenMPUtilityConstruct &c) -> SourcePosition {
const CharBlock &source{c.source};
return (parsing->allCooked().GetSourcePositionRange(source))->first;
return parsing->allCooked().GetSourcePositionRange(source)->first;
},
},
c.u);
Expand Down Expand Up @@ -157,14 +151,9 @@ std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) {
return normalize_construct_name(source.ToString());
},
[&](const OpenMPAtomicConstruct &c) -> std::string {
return std::visit(
[&](const auto &c) {
// Get source from the verbatim fields
const CharBlock &source{std::get<Verbatim>(c.t).source};
return "atomic-" +
normalize_construct_name(source.ToString());
},
c.u);
auto &dirSpec = std::get<OmpDirectiveSpecification>(c.t);
auto &dirName = std::get<OmpDirectiveName>(dirSpec.t);
return normalize_construct_name(dirName.source.ToString());
},
[&](const OpenMPUtilityConstruct &c) -> std::string {
const CharBlock &source{c.source};
Expand Down
12 changes: 0 additions & 12 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,15 +531,6 @@ class ParseTreeDumper {
NODE(parser, OmpAtClause)
NODE_ENUM(OmpAtClause, ActionTime)
NODE_ENUM(OmpSeverityClause, Severity)
NODE(parser, OmpAtomic)
NODE(parser, OmpAtomicCapture)
NODE(OmpAtomicCapture, Stmt1)
NODE(OmpAtomicCapture, Stmt2)
NODE(parser, OmpAtomicCompare)
NODE(parser, OmpAtomicCompareIfStmt)
NODE(parser, OmpAtomicRead)
NODE(parser, OmpAtomicUpdate)
NODE(parser, OmpAtomicWrite)
NODE(parser, OmpBeginBlockDirective)
NODE(parser, OmpBeginLoopDirective)
NODE(parser, OmpBeginSectionsDirective)
Expand Down Expand Up @@ -586,7 +577,6 @@ class ParseTreeDumper {
NODE(parser, OmpDoacrossClause)
NODE(parser, OmpDestroyClause)
NODE(parser, OmpEndAllocators)
NODE(parser, OmpEndAtomic)
NODE(parser, OmpEndBlockDirective)
NODE(parser, OmpEndCriticalDirective)
NODE(parser, OmpEndLoopDirective)
Expand Down Expand Up @@ -715,8 +705,6 @@ class ParseTreeDumper {
NODE(parser, OpenMPDeclareMapperConstruct)
NODE_ENUM(common, OmpMemoryOrderType)
NODE(parser, OmpMemoryOrderClause)
NODE(parser, OmpAtomicClause)
NODE(parser, OmpAtomicClauseList)
NODE(parser, OmpAtomicDefaultMemOrderClause)
NODE(parser, OpenMPDepobjConstruct)
NODE(parser, OpenMPUtilityConstruct)
Expand Down
111 changes: 27 additions & 84 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -4857,94 +4857,37 @@ struct OmpMemoryOrderClause {
CharBlock source;
};

// 2.17.7 Atomic construct
// atomic-clause -> memory-order-clause | HINT(hint-expression) |
// FAIL(memory-order)
struct OmpAtomicClause {
UNION_CLASS_BOILERPLATE(OmpAtomicClause);
CharBlock source;
std::variant<OmpMemoryOrderClause, OmpFailClause, OmpHintClause> u;
};

// atomic-clause-list -> [atomic-clause, [atomic-clause], ...]
struct OmpAtomicClauseList {
WRAPPER_CLASS_BOILERPLATE(OmpAtomicClauseList, std::list<OmpAtomicClause>);
CharBlock source;
};

// END ATOMIC
EMPTY_CLASS(OmpEndAtomic);

// ATOMIC READ
struct OmpAtomicRead {
TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
CharBlock source;
std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
t;
};

// ATOMIC WRITE
struct OmpAtomicWrite {
TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
CharBlock source;
std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
t;
};

// ATOMIC UPDATE
struct OmpAtomicUpdate {
TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
CharBlock source;
std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
t;
};

// ATOMIC CAPTURE
struct OmpAtomicCapture {
TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture);
CharBlock source;
WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList, Stmt1, Stmt2,
OmpEndAtomic>
t;
};

struct OmpAtomicCompareIfStmt {
UNION_CLASS_BOILERPLATE(OmpAtomicCompareIfStmt);
std::variant<common::Indirection<IfStmt>, common::Indirection<IfConstruct>> u;
};

// ATOMIC COMPARE (OpenMP 5.1, OPenMP 5.2 spec: 15.8.4)
struct OmpAtomicCompare {
TUPLE_CLASS_BOILERPLATE(OmpAtomicCompare);
struct OpenMPAtomicConstruct {
llvm::omp::Clause GetKind() const;
bool IsCapture() const;
bool IsCompare() const;
TUPLE_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
CharBlock source;
std::tuple<OmpAtomicClauseList, Verbatim, OmpAtomicClauseList,
OmpAtomicCompareIfStmt, std::optional<OmpEndAtomic>>
std::tuple<OmpDirectiveSpecification, Block,
std::optional<OmpDirectiveSpecification>>
t;
};

// ATOMIC
struct OmpAtomic {
TUPLE_CLASS_BOILERPLATE(OmpAtomic);
CharBlock source;
std::tuple<Verbatim, OmpAtomicClauseList, Statement<AssignmentStmt>,
std::optional<OmpEndAtomic>>
t;
};
// Information filled out during semantic checks to avoid duplication
// of analyses.
struct Analysis {
static constexpr int None = 0;
static constexpr int Read = 1;
static constexpr int Write = 2;
static constexpr int Update = Read | Write;
static constexpr int Action = 3; // Bitmask for None, Read, Write, Update
static constexpr int IfTrue = 4;
static constexpr int IfFalse = 8;
static constexpr int Condition = 12; // Bitmask for IfTrue, IfFalse

struct Op {
int what;
AssignmentStmt::TypedAssignment assign;
};
TypedExpr atom, cond;
Op op0, op1;
};

// 2.17.7 atomic ->
// ATOMIC [atomic-clause-list] atomic-construct [atomic-clause-list] |
// ATOMIC [atomic-clause-list]
// atomic-construct -> READ | WRITE | UPDATE | CAPTURE | COMPARE
struct OpenMPAtomicConstruct {
UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
OmpAtomicCompare, OmpAtomic>
u;
mutable Analysis analysis;
};

// OpenMP directives that associate with loop(s)
Expand Down
16 changes: 16 additions & 0 deletions flang/include/flang/Semantics/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -782,5 +782,21 @@ inline bool checkForSymbolMatch(
}
return false;
}

/// If the top-level operation (ignoring parentheses) is either an
/// evaluate::FunctionRef, or a specialization of evaluate::Operation,
/// then return the list of arguments (wrapped in SomeExpr). Otherwise,
/// return the "expr" but with top-level parentheses stripped.
std::vector<SomeExpr> GetOpenMPTopLevelArguments(const SomeExpr &expr);

/// Both "expr" and "x" have the form of SomeType(SomeKind(...)[1]).
/// Check if "expr" is
/// SomeType(SomeKind(Type(
/// Convert
/// SomeKind(...)[2])))
/// where SomeKind(...) [1] and [2] are equal, and the Convert preserves
/// TypeCategory.
bool IsSameOrResizeOf(const SomeExpr &expr, const SomeExpr &x);

} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_TOOLS_H_
40 changes: 20 additions & 20 deletions flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,26 +332,26 @@ getSource(const semantics::SemanticsContext &semaCtx,
const parser::CharBlock *source = nullptr;

auto ompConsVisit = [&](const parser::OpenMPConstruct &x) {
std::visit(common::visitors{
[&](const parser::OpenMPSectionsConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPLoopConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPBlockConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPCriticalConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPAtomicConstruct &x) {
std::visit([&](const auto &x) { source = &x.source; },
x.u);
},
[&](const auto &x) { source = &x.source; },
},
x.u);
std::visit(
common::visitors{
[&](const parser::OpenMPSectionsConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPLoopConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPBlockConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPCriticalConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const parser::OpenMPAtomicConstruct &x) {
source = &std::get<parser::OmpDirectiveSpecification>(x.t).source;
},
[&](const auto &x) { source = &x.source; },
},
x.u);
};

eval.visit(common::visitors{
Expand Down
Loading