Skip to content
Merged
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
4 changes: 4 additions & 0 deletions flang/include/flang/Evaluate/check-expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ extern template std::optional<bool> IsContiguous(
const CoarrayRef &, FoldingContext &);
extern template std::optional<bool> IsContiguous(
const Symbol &, FoldingContext &);
static inline std::optional<bool> IsContiguous(
const SymbolRef &s, FoldingContext &c) {
return IsContiguous(s.get(), c);
}
template <typename A>
bool IsSimplyContiguous(const A &x, FoldingContext &context) {
return IsContiguous(x, context).value_or(false);
Expand Down
5 changes: 5 additions & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ class ParseTreeDumper {
NODE(parser, OmpEndCriticalDirective)
NODE(parser, OmpEndLoopDirective)
NODE(parser, OmpEndSectionsDirective)
NODE(parser, OmpFromClause)
NODE_ENUM(OmpFromClause, Expectation)
NODE(parser, OmpIfClause)
NODE_ENUM(OmpIfClause, DirectiveNameModifier)
NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
Expand Down Expand Up @@ -581,6 +583,9 @@ class ParseTreeDumper {
NODE(parser, OmpSectionBlocks)
NODE(parser, OmpSectionsDirective)
NODE(parser, OmpSimpleStandaloneDirective)
NODE(parser, OmpToClause)
// No NODE_ENUM for OmpToClause::Expectation, because it's an alias
// for OmpFromClause::Expectation.
NODE(parser, Only)
NODE(parser, OpenACCAtomicConstruct)
NODE(parser, OpenACCBlockConstruct)
Expand Down
42 changes: 42 additions & 0 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3582,6 +3582,26 @@ struct OmpDeviceTypeClause {
WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type);
};

// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
//
// from-clause ->
// FROM(locator-list) |
// FROM(mapper-modifier: locator-list) | // since 5.0
// FROM(motion-modifier[,] ...: locator-list) // since 5.1
// motion-modifier ->
// PRESENT | mapper-modifier | iterator-modifier
struct OmpFromClause {
ENUM_CLASS(Expectation, Present);
TUPLE_CLASS_BOILERPLATE(OmpFromClause);

// As in the case of MAP, modifiers are parsed as lists, even if they
// are unique. These restrictions will be checked in semantic checks.
std::tuple<std::optional<std::list<Expectation>>,
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
bool> // were the modifiers comma-separated?
t;
};

// OMP 5.2 12.6.1 grainsize-clause -> grainsize ([prescriptiveness :] value)
struct OmpGrainsizeClause {
TUPLE_CLASS_BOILERPLATE(OmpGrainsizeClause);
Expand Down Expand Up @@ -3718,6 +3738,28 @@ struct OmpScheduleClause {
t;
};

// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
//
// to-clause (in DECLARE TARGET) ->
// TO(extended-list) | // until 5.1
// to-clause (in TARGET UPDATE) ->
// TO(locator-list) |
// TO(mapper-modifier: locator-list) | // since 5.0
// TO(motion-modifier[,] ...: locator-list) // since 5.1
// motion-modifier ->
// PRESENT | mapper-modifier | iterator-modifier
struct OmpToClause {
using Expectation = OmpFromClause::Expectation;
TUPLE_CLASS_BOILERPLATE(OmpToClause);

// As in the case of MAP, modifiers are parsed as lists, even if they
// are unique. These restrictions will be checked in semantic checks.
std::tuple<std::optional<std::list<Expectation>>,
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
bool> // were the modifiers comma-separated?
t;
};

// OMP 5.2 12.6.2 num_tasks-clause -> num_tasks ([prescriptiveness :] value)
struct OmpNumTasksClause {
TUPLE_CLASS_BOILERPLATE(OmpNumTasksClause);
Expand Down
14 changes: 10 additions & 4 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1019,16 +1019,22 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,

auto callbackFn = [&](const auto &clause, const parser::CharBlock &source) {
mlir::Location clauseLocation = converter.genLocation(source);

const auto &[expectation, mapper, iterator, objects] = clause.t;
// TODO Support motion modifiers: present, mapper, iterator.
if (expectation) {
TODO(clauseLocation, "PRESENT modifier is not supported yet");
} else if (mapper) {
TODO(clauseLocation, "Mapper modifier is not supported yet");
} else if (iterator) {
TODO(clauseLocation, "Iterator modifier is not supported yet");
}
constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
std::is_same_v<llvm::remove_cvref_t<decltype(clause)>, omp::clause::To>
? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
: llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;

processMapObjects(stmtCtx, clauseLocation, std::get<ObjectList>(clause.t),
mapTypeBits, parentMemberIndices, result.mapVars,
mapSymbols);
processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits,
parentMemberIndices, result.mapVars, mapSymbols);
};

bool clauseFound = findRepeatableClause<omp::clause::To>(callbackFn);
Expand Down
79 changes: 69 additions & 10 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -728,21 +728,51 @@ Firstprivate make(const parser::OmpClause::Firstprivate &inp,

From make(const parser::OmpClause::From &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return From{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt,
/*Iterator=*/std::nullopt,
/*LocatorList=*/makeObjects(inp.v, semaCtx)}};
// inp.v -> parser::OmpFromClause
using wrapped = parser::OmpFromClause;

CLAUSET_ENUM_CONVERT( //
convert, parser::OmpFromClause::Expectation, From::Expectation,
// clang-format off
MS(Present, Present)
// clang-format on
);

auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
auto &t1 =
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);

assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
assert((!t1 || t1->size() == 1) && "Only one iterator modifier allowed");

auto expectation = [&]() -> std::optional<From::Expectation> {
if (t0)
return convert(t0->front());
return std::nullopt;
}();

auto iterator = [&]() -> std::optional<Iterator> {
if (t1)
return makeIterator(t1->front(), semaCtx);
return std::nullopt;
}();

return From{{/*Expectation=*/std::move(expectation), /*Mapper=*/std::nullopt,
/*Iterator=*/std::move(iterator),
/*LocatorList=*/makeObjects(t2, semaCtx)}};
}

// Full: empty

Grainsize make(const parser::OmpClause::Grainsize &inp,
semantics::SemanticsContext &semaCtx) {
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpGrainsizeClause
using wrapped = parser::OmpGrainsizeClause;

CLAUSET_ENUM_CONVERT( //
convert, parser::OmpGrainsizeClause::Prescriptiveness, Grainsize::Prescriptiveness,
convert, parser::OmpGrainsizeClause::Prescriptiveness,
Grainsize::Prescriptiveness,
// clang-format off
MS(Strict, Strict)
// clang-format on
Expand Down Expand Up @@ -1274,10 +1304,39 @@ ThreadLimit make(const parser::OmpClause::ThreadLimit &inp,

To make(const parser::OmpClause::To &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpObjectList
return To{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt,
/*Iterator=*/std::nullopt,
/*LocatorList=*/makeObjects(inp.v, semaCtx)}};
// inp.v -> parser::OmpToClause
using wrapped = parser::OmpToClause;

CLAUSET_ENUM_CONVERT( //
convert, parser::OmpToClause::Expectation, To::Expectation,
// clang-format off
MS(Present, Present)
// clang-format on
);

auto &t0 = std::get<std::optional<std::list<wrapped::Expectation>>>(inp.v.t);
auto &t1 =
std::get<std::optional<std::list<parser::OmpIteratorModifier>>>(inp.v.t);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);

assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed");
assert((!t1 || t1->size() == 1) && "Only one iterator modifier allowed");

auto expectation = [&]() -> std::optional<To::Expectation> {
if (t0)
return convert(t0->front());
return std::nullopt;
}();

auto iterator = [&]() -> std::optional<Iterator> {
if (t1)
return makeIterator(t1->front(), semaCtx);
return std::nullopt;
}();

return To{{/*Expectation=*/std::move(expectation), /*Mapper=*/std::nullopt,
/*Iterator=*/std::move(iterator),
/*LocatorList=*/makeObjects(t2, semaCtx)}};
}

// UnifiedAddress: empty
Expand Down
65 changes: 62 additions & 3 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,40 @@ template <typename Separator> struct MapModifiers {
const Separator sep_;
};

// This is almost exactly the same thing as MapModifiers. It has the same
// issue (it expects modifiers in a specific order), and the fix for that
// will change how modifiers are parsed. Instead of making this code more
// generic, make it simple, and generalize after the fix is in place.
template <typename Separator> struct MotionModifiers {
constexpr MotionModifiers(Separator sep) : sep_(sep) {}
constexpr MotionModifiers(const MotionModifiers &) = default;
constexpr MotionModifiers(MotionModifiers &&) = default;

// Parsing of mappers if not implemented yet.
using ExpParser = Parser<OmpFromClause::Expectation>;
using IterParser = Parser<OmpIteratorModifier>;
using ModParser = ConcatSeparated<Separator, ExpParser, IterParser>;

using resultType = typename ModParser::resultType;

std::optional<resultType> Parse(ParseState &state) const {
auto mp{ModParser(sep_, ExpParser{}, IterParser{})};
auto mods{mp.Parse(state)};
// The ModParser always "succeeds", i.e. even if the input is junk, it
// will return a tuple filled with nullopts. If any of the components
// is not a nullopt, expect a ":".
if (std::apply([](auto &&...opts) { return (... || !!opts); }, *mods)) {
if (!attempt(":"_tok).Parse(state)) {
return std::nullopt;
}
}
return std::move(mods);
}

private:
const Separator sep_;
};

// OpenMP Clauses

// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple |
Expand Down Expand Up @@ -382,6 +416,31 @@ TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
maybe(Parser<OmpIteratorModifier>{} / ","_tok),
Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})))

TYPE_PARSER(construct<OmpFromClause::Expectation>(
"PRESENT" >> pure(OmpFromClause::Expectation::Present)))

template <typename MotionClause, bool CommasEverywhere>
static inline MotionClause makeMotionClause(
std::tuple<std::optional<std::list<typename MotionClause::Expectation>>,
std::optional<std::list<OmpIteratorModifier>>> &&mods,
OmpObjectList &&objs) {
auto &&[exp, iter] = std::move(mods);
return MotionClause(
std::move(exp), std::move(iter), std::move(objs), CommasEverywhere);
}

TYPE_PARSER(construct<OmpFromClause>(
applyFunction<OmpFromClause>(makeMotionClause<OmpFromClause, true>,
MotionModifiers(","_tok), Parser<OmpObjectList>{}) ||
applyFunction<OmpFromClause>(makeMotionClause<OmpFromClause, false>,
MotionModifiers(maybe(","_tok)), Parser<OmpObjectList>{})))

TYPE_PARSER(construct<OmpToClause>(
applyFunction<OmpToClause>(makeMotionClause<OmpToClause, true>,
MotionModifiers(","_tok), Parser<OmpObjectList>{}) ||
applyFunction<OmpToClause>(makeMotionClause<OmpToClause, false>,
MotionModifiers(maybe(","_tok)), Parser<OmpObjectList>{})))

// 2.15.3.7 LINEAR (linear-list: linear-step)
// linear-list -> list | modifier(list)
// linear-modifier -> REF | VAL | UVAL
Expand Down Expand Up @@ -475,11 +534,11 @@ TYPE_PARSER(
parenthesized(scalarIntExpr))) ||
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
parenthesized(scalarLogicalExpr))) ||
"FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) ||
"FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
parenthesized(Parser<OmpObjectList>{}))) ||
"FROM" >> construct<OmpClause>(construct<OmpClause::From>(
parenthesized(Parser<OmpObjectList>{}))) ||
parenthesized(Parser<OmpFromClause>{}))) ||
"FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) ||
"GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>(
parenthesized(Parser<OmpGrainsizeClause>{}))) ||
"HAS_DEVICE_ADDR" >>
Expand Down Expand Up @@ -554,7 +613,7 @@ TYPE_PARSER(
"THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>(
parenthesized(scalarIntExpr))) ||
"TO" >> construct<OmpClause>(construct<OmpClause::To>(
parenthesized(Parser<OmpObjectList>{}))) ||
parenthesized(Parser<OmpToClause>{}))) ||
"USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
parenthesized(Parser<OmpObjectList>{}))) ||
"USE_DEVICE_ADDR" >>
Expand Down
43 changes: 43 additions & 0 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2138,6 +2138,27 @@ class UnparseVisitor {
Put(",");
Walk(std::get<std::optional<ScalarIntConstantExpr>>(x.t));
}
void Unparse(const OmpFromClause &x) {
auto &expect{
std::get<std::optional<std::list<OmpFromClause::Expectation>>>(x.t)};
auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
bool needComma{false};
if (expect) {
Walk(*expect);
needComma = true;
}
if (iter) {
if (needComma) {
Put(", ");
}
Walk(*iter);
needComma = true;
}
if (needComma) {
Put(": ");
}
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpIfClause &x) {
Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t), ":");
Walk(std::get<ScalarLogicalExpr>(x.t));
Expand Down Expand Up @@ -2241,6 +2262,27 @@ class UnparseVisitor {
Walk(":",
std::get<std::optional<OmpDefaultmapClause::VariableCategory>>(x.t));
}
void Unparse(const OmpToClause &x) {
auto &expect{
std::get<std::optional<std::list<OmpToClause::Expectation>>>(x.t)};
auto &iter{std::get<std::optional<std::list<OmpIteratorModifier>>>(x.t)};
bool needComma{false};
if (expect) {
Walk(*expect);
needComma = true;
}
if (iter) {
if (needComma) {
Put(", ");
}
Walk(*iter);
needComma = true;
}
if (needComma) {
Put(": ");
}
Walk(std::get<OmpObjectList>(x.t));
}
#define GEN_FLANG_CLAUSE_UNPARSE
#include "llvm/Frontend/OpenMP/OMP.inc"
void Unparse(const OmpLoopDirective &x) {
Expand Down Expand Up @@ -2858,6 +2900,7 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
WALK_NESTED_ENUM(
OmpReductionClause, ReductionModifier) // OMP reduction-modifier
WALK_NESTED_ENUM(OmpFromClause, Expectation) // OMP motion-expectation
WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type
Expand Down
Loading
Loading