Skip to content

[flang][OpenMP] Parsing support for iterator in DEPEND clause #113622

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 13 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 10 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
4 changes: 2 additions & 2 deletions flang/examples/FeatureList/FeatureList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,8 @@ struct NodeVisitor {
READ_FEATURE(OmpDependClause::InOut)
READ_FEATURE(OmpDependClause::Sink)
READ_FEATURE(OmpDependClause::Source)
READ_FEATURE(OmpDependenceType)
READ_FEATURE(OmpDependenceType::Type)
READ_FEATURE(OmpTaskDependenceType)
READ_FEATURE(OmpTaskDependenceType::Type)
READ_FEATURE(OmpDependSinkVec)
READ_FEATURE(OmpDependSinkVecLength)
READ_FEATURE(OmpEndAllocators)
Expand Down
4 changes: 2 additions & 2 deletions flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) {
clauseDetails +=
"modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";";
}
void OpenMPCounterVisitor::Post(const OmpDependenceType::Type &c) {
void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Type &c) {
clauseDetails +=
"type=" + std::string{OmpDependenceType::EnumToString(c)} + ";";
"type=" + std::string{OmpTaskDependenceType::EnumToString(c)} + ";";
}
void OpenMPCounterVisitor::Post(const OmpMapClause::Type &c) {
clauseDetails += "type=" + std::string{OmpMapClause::EnumToString(c)} + ";";
Expand Down
2 changes: 1 addition & 1 deletion flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ struct OpenMPCounterVisitor {
void Post(const OmpDeviceTypeClause::Type &c);
void Post(const OmpScheduleModifierType::ModType &c);
void Post(const OmpLinearModifier::Type &c);
void Post(const OmpDependenceType::Type &c);
void Post(const OmpTaskDependenceType::Type &c);
void Post(const OmpMapClause::Type &c);
void Post(const OmpScheduleClause::ScheduleType &c);
void Post(const OmpIfClause::DirectiveNameModifier &c);
Expand Down
4 changes: 2 additions & 2 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,8 @@ class ParseTreeDumper {
NODE(OmpDependClause, InOut)
NODE(OmpDependClause, Sink)
NODE(OmpDependClause, Source)
NODE(parser, OmpDependenceType)
NODE_ENUM(OmpDependenceType, Type)
NODE(parser, OmpTaskDependenceType)
NODE_ENUM(OmpTaskDependenceType, Type)
NODE(parser, OmpDependSinkVec)
NODE(parser, OmpDependSinkVecLength)
NODE(parser, OmpEndAllocators)
Expand Down
34 changes: 24 additions & 10 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3439,6 +3439,18 @@ struct OmpObject {

WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);

// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
//
// task-dependence-type -> // "dependence-type" in 5.1 and before
// IN | OUT | INOUT | // since 4.5
// SOURCE | SINK | // since 4.5, until 5.1
// MUTEXINOUTSET | DEPOBJ | // since 5.0
// INOUTSET // since 5.2
struct OmpTaskDependenceType {
ENUM_CLASS(Type, In, Out, Inout, Source, Sink)
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type);
};

// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple
// iterator-modifier -> iterator-specifier-list
struct OmpIteratorSpecifier {
Expand Down Expand Up @@ -3534,27 +3546,29 @@ struct OmpDependSinkVecLength {
std::tuple<DefinedOperator, ScalarIntConstantExpr> t;
};

// 2.13.9 depend-vec -> iterator [+/- depend-vec-length],...,iterator[...]
// 2.13.9 depend-vec -> induction-variable [depend-vec-length], ...
struct OmpDependSinkVec {
TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec);
std::tuple<Name, std::optional<OmpDependSinkVecLength>> t;
};

// 2.13.9 depend-type -> IN | OUT | INOUT | SOURCE | SINK
struct OmpDependenceType {
ENUM_CLASS(Type, In, Out, Inout, Source, Sink)
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
};

// 2.13.9 depend-clause -> DEPEND (((IN | OUT | INOUT) : variable-name-list) |
// SOURCE | SINK : depend-vec)
// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289], [5.2:323-324]
//
// depend-clause ->
// DEPEND(SOURCE) | // since 4.5, until 5.1
// DEPEND(SINK: depend-vec) | // since 4.5, until 5.1
// DEPEND([depend-modifier,]dependence-type: locator-list) // since 4.5
//
// depend-modifier -> iterator-modifier // since 5.0
struct OmpDependClause {
UNION_CLASS_BOILERPLATE(OmpDependClause);
EMPTY_CLASS(Source);
WRAPPER_CLASS(Sink, std::list<OmpDependSinkVec>);
struct InOut {
TUPLE_CLASS_BOILERPLATE(InOut);
std::tuple<OmpDependenceType, std::list<Designator>> t;
std::tuple<std::optional<OmpIteratorModifier>, OmpTaskDependenceType,
OmpObjectList>
t;
};
std::variant<Source, Sink, InOut> u;
};
Expand Down
62 changes: 34 additions & 28 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,35 +795,41 @@ bool ClauseProcessor::processCopyprivate(
bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

return findRepeatableClause<omp::clause::Depend>(
[&](const omp::clause::Depend &clause, const parser::CharBlock &) {
using Depend = omp::clause::Depend;
assert(std::holds_alternative<Depend::WithLocators>(clause.u) &&
"Only the modern form is handled at the moment");
auto &modern = std::get<Depend::WithLocators>(clause.u);
auto kind = std::get<Depend::TaskDependenceType>(modern.t);
auto &objects = std::get<omp::ObjectList>(modern.t);

mlir::omp::ClauseTaskDependAttr dependTypeOperand =
genDependKindAttr(firOpBuilder, kind);
result.dependKinds.append(objects.size(), dependTypeOperand);

for (const omp::Object &object : objects) {
assert(object.ref() && "Expecting designator");

if (evaluate::ExtractSubstring(*object.ref())) {
TODO(converter.getCurrentLocation(),
"substring not supported for task depend");
} else if (evaluate::IsArrayElement(*object.ref())) {
TODO(converter.getCurrentLocation(),
"array sections not supported for task depend");
}
auto process = [&](const omp::clause::Depend &clause,
const parser::CharBlock &) {
using Depend = omp::clause::Depend;
assert(std::holds_alternative<Depend::DepType>(clause.u) &&
"Only the form with depenence type is handled at the moment");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

auto &depType = std::get<Depend::DepType>(clause.u);
auto kind = std::get<Depend::TaskDependenceType>(depType.t);
auto &objects = std::get<omp::ObjectList>(depType.t);

if (std::get<std::optional<omp::clause::Iterator>>(depType.t)) {
TODO(converter.getCurrentLocation(),
"Support for iterator modifiers is not implemented yet");
}
mlir::omp::ClauseTaskDependAttr dependTypeOperand =
genDependKindAttr(firOpBuilder, kind);
result.dependKinds.append(objects.size(), dependTypeOperand);

for (const omp::Object &object : objects) {
assert(object.ref() && "Expecting designator");

if (evaluate::ExtractSubstring(*object.ref())) {
TODO(converter.getCurrentLocation(),
"substring not supported for task depend");
} else if (evaluate::IsArrayElement(*object.ref())) {
TODO(converter.getCurrentLocation(),
"array sections not supported for task depend");
}

semantics::Symbol *sym = object.sym();
const mlir::Value variable = converter.getSymbolAddress(*sym);
result.dependVars.push_back(variable);
}
});
semantics::Symbol *sym = object.sym();
const mlir::Value variable = converter.getSymbolAddress(*sym);
result.dependVars.push_back(variable);
}
};

return findRepeatableClause<omp::clause::Depend>(process);
}

bool ClauseProcessor::processHasDeviceAddr(
Expand Down
23 changes: 12 additions & 11 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ Depend make(const parser::OmpClause::Depend &inp,
using Iteration = Doacross::Vector::value_type; // LoopIterationT

CLAUSET_ENUM_CONVERT( //
convert1, parser::OmpDependenceType::Type, Depend::TaskDependenceType,
convert1, parser::OmpTaskDependenceType::Type, Depend::TaskDependenceType,
// clang-format off
MS(In, In)
MS(Out, Out)
Expand Down Expand Up @@ -593,17 +593,18 @@ Depend make(const parser::OmpClause::Depend &inp,
return Doacross{{/*DependenceType=*/Doacross::DependenceType::Sink,
/*Vector=*/makeList(s.v, convert2)}};
},
// Depend::WithLocators
// Depend::DepType
[&](const wrapped::InOut &s) -> Variant {
auto &t0 = std::get<parser::OmpDependenceType>(s.t);
auto &t1 = std::get<std::list<parser::Designator>>(s.t);
auto convert4 = [&](const parser::Designator &t) {
return makeObject(t, semaCtx);
};
return Depend::WithLocators{
{/*TaskDependenceType=*/convert1(t0.v),
/*Iterator=*/std::nullopt,
/*LocatorList=*/makeList(t1, convert4)}};
auto &t0 =
std::get<std::optional<parser::OmpIteratorModifier>>(s.t);
auto &t1 = std::get<parser::OmpTaskDependenceType>(s.t);
auto &t2 = std::get<parser::OmpObjectList>(s.t);

auto &&maybeIter = maybeApply(
[&](auto &&s) { return makeIterator(s, semaCtx); }, t0);
return Depend::DepType{{/*TaskDependenceType=*/convert1(t1.v),
/*Iterator=*/std::move(maybeIter),
/*LocatorList=*/makeObjects(t2, semaCtx)}};
},
},
inp.v.u)};
Expand Down
11 changes: 6 additions & 5 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,18 +365,19 @@ TYPE_PARSER(construct<OmpDependSinkVecLength>(
TYPE_PARSER(
construct<OmpDependSinkVec>(name, maybe(Parser<OmpDependSinkVecLength>{})))

TYPE_PARSER(
construct<OmpDependenceType>("IN"_id >> pure(OmpDependenceType::Type::In) ||
"INOUT" >> pure(OmpDependenceType::Type::Inout) ||
"OUT" >> pure(OmpDependenceType::Type::Out)))
TYPE_PARSER(construct<OmpTaskDependenceType>(
"IN"_id >> pure(OmpTaskDependenceType::Type::In) ||
"INOUT" >> pure(OmpTaskDependenceType::Type::Inout) ||
"OUT" >> pure(OmpTaskDependenceType::Type::Out)))

TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
construct<OmpDependClause>(construct<OmpDependClause::Sink>(
"SINK :" >> nonemptyList(Parser<OmpDependSinkVec>{}))) ||
construct<OmpDependClause>(
construct<OmpDependClause::Source>("SOURCE"_tok)) ||
construct<OmpDependClause>(construct<OmpDependClause::InOut>(
Parser<OmpDependenceType>{}, ":" >> nonemptyList(designator))))
maybe(Parser<OmpIteratorModifier>{} / ","_tok),
Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})))

// 2.15.3.7 LINEAR (linear-list: linear-step)
// linear-list -> list | modifier(list)
Expand Down
6 changes: 3 additions & 3 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2206,9 +2206,9 @@ class UnparseVisitor {
}
void Unparse(const OmpDependClause::InOut &x) {
Put("(");
Walk(std::get<OmpDependenceType>(x.t));
Walk(std::get<OmpTaskDependenceType>(x.t));
Put(":");
Walk(std::get<std::list<Designator>>(x.t), ",");
Walk(std::get<OmpObjectList>(x.t));
Put(")");
}
bool Pre(const OmpDependClause &x) {
Expand Down Expand Up @@ -2816,7 +2816,7 @@ class UnparseVisitor {
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type
WALK_NESTED_ENUM(OmpTaskDependenceType, Type) // OMP task-dependence-type
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
Expand Down
57 changes: 39 additions & 18 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ namespace Fortran::semantics {
CheckAllowedClause(llvm::omp::Y); \
}

std::string ThisVersion(unsigned version) {
std::string tv{
std::to_string(version / 10) + "." + std::to_string(version % 10)};
return "OpenMP v" + tv;
}

std::string TryVersion(unsigned version) {
return "try -fopenmp-version=" + std::to_string(version);
}

// 'OmpWorkshareBlockChecker' is used to check the validity of the assignment
// statements and the expressions enclosed in an OpenMP Workshare construct
class OmpWorkshareBlockChecker {
Expand Down Expand Up @@ -200,14 +210,10 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
auto clauseName{parser::ToUpperCaseLetters(getClauseName(clause).str())};
auto dirName{parser::ToUpperCaseLetters(getDirectiveName(dir).str())};

std::string thisVersion{
std::to_string(version / 10) + "." + std::to_string(version % 10)};
std::string goodVersion{std::to_string(allowedInVersion)};

context_.Say(dirCtx.clauseSource,
"%s clause is not allowed on directive %s in OpenMP v%s, "
"try -fopenmp-version=%d"_err_en_US,
clauseName, dirName, thisVersion, allowedInVersion);
"%s clause is not allowed on directive %s in %s, %s"_err_en_US,
clauseName, dirName, ThisVersion(version),
TryVersion(allowedInVersion));
}
}
return CheckAllowed(clause);
Expand Down Expand Up @@ -3283,18 +3289,33 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
parser::ToUpperCaseLetters(getDirectiveName(GetContext().directive)));
}
if (const auto *inOut{std::get_if<parser::OmpDependClause::InOut>(&x.v.u)}) {
const auto &designators{std::get<std::list<parser::Designator>>(inOut->t)};
for (const auto &ele : designators) {
if (const auto *dataRef{std::get_if<parser::DataRef>(&ele.u)}) {
CheckDependList(*dataRef);
if (const auto *arr{
std::get_if<common::Indirection<parser::ArrayElement>>(
&dataRef->u)}) {
CheckArraySection(arr->value(), GetLastName(*dataRef),
llvm::omp::Clause::OMPC_depend);
for (const auto &object : std::get<parser::OmpObjectList>(inOut->t).v) {
if (const auto *name{std::get_if<parser::Name>(&object.u)}) {
context_.Say(GetContext().clauseSource,
"Common block name ('%s') cannot appear in a DEPEND "
"clause"_err_en_US,
name->ToString());
} else if (auto *designator{std::get_if<parser::Designator>(&object.u)}) {
if (auto *dataRef{std::get_if<parser::DataRef>(&designator->u)}) {
CheckDependList(*dataRef);
if (const auto *arr{
std::get_if<common::Indirection<parser::ArrayElement>>(
&dataRef->u)}) {
CheckArraySection(arr->value(), GetLastName(*dataRef),
llvm::omp::Clause::OMPC_depend);
}
}
}
}
if (std::get<std::optional<parser::OmpIteratorModifier>>(inOut->t)) {
unsigned version{context_.langOptions().OpenMPVersion};
unsigned allowedInVersion = 50;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unsigned allowedInVersion = 50;
unsigned allowedInVersion{50};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (version < allowedInVersion) {
context_.Say(GetContext().clauseSource,
"Iterator modifiers are not supported in %s, %s"_warn_en_US,
ThisVersion(version), TryVersion(allowedInVersion));
}
}
}
}

Expand Down Expand Up @@ -3367,8 +3388,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
std::to_string(version / 10) + "." + std::to_string(version % 10)};
context_.Say(GetContext().clauseSource,
"LASTPRIVATE clause with CONDITIONAL modifier is not "
"allowed in OpenMP v%s, try -fopenmp-version=%d"_err_en_US,
thisVersion, allowedInVersion);
"allowed in %s, %s"_err_en_US,
ThisVersion(version), TryVersion(allowedInVersion));
}
}
}
Expand Down
27 changes: 17 additions & 10 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,20 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
bool Pre(const parser::OpenMPAllocatorsConstruct &);
void Post(const parser::OpenMPAllocatorsConstruct &);

void Post(const parser::OmpObjectList &x) {
// The objects from OMP clauses should have already been resolved,
// except common blocks (the ResolveNamesVisitor does not visit
// parser::Name, those are dealt with as members of other structures).
// Iterate over elements of x, and resolve any common blocks that
// are still unresolved.
for (const parser::OmpObject &obj : x.v) {
auto *name{std::get_if<parser::Name>(&obj.u)};
if (name && !name->symbol) {
Resolve(*name, currScope().MakeCommonBlock(name->source));
}
}
}

// 2.15.3 Data-Sharing Attribute Clauses
void Post(const parser::OmpDefaultClause &);
bool Pre(const parser::OmpClause::Shared &x) {
Expand Down Expand Up @@ -531,16 +545,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
return false;
}

bool Pre(const parser::OmpDependClause &x) {
if (const auto *dependSink{
std::get_if<parser::OmpDependClause::Sink>(&x.u)}) {
const auto &dependSinkVec{dependSink->v};
for (const auto &dependSinkElement : dependSinkVec) {
const auto &name{std::get<parser::Name>(dependSinkElement.t)};
ResolveName(&name);
}
}
return false;
void Post(const parser::OmpDependSinkVec &x) {
const auto &name{std::get<parser::Name>(x.t)};
ResolveName(&name);
}

bool Pre(const parser::OmpClause::UseDevicePtr &x) {
Expand Down
10 changes: 10 additions & 0 deletions flang/test/Lower/OpenMP/Todo/depend-clause.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s

!CHECK: Support for iterator modifiers is not implemented yet
subroutine f00(x)
integer :: x(10)
!$omp task depend(iterator(i = 1:10), in: x(i))
x = 0
!$omp end task
end
Loading
Loading