[flang][OpenMP] Use new modifiers in IF/LASTPRIVATE (#118128)
The usual changes, added more references to OpenMP specs.
This commit is contained in:
parent
b8daa45a56
commit
33faa8285f
@ -492,7 +492,8 @@ public:
|
||||
READ_FEATURE(OmpPrescriptiveness)
|
||||
READ_FEATURE(OmpPrescriptiveness::Value)
|
||||
READ_FEATURE(OmpIfClause)
|
||||
READ_FEATURE(OmpIfClause::DirectiveNameModifier)
|
||||
READ_FEATURE(OmpIfClause::Modifier)
|
||||
READ_FEATURE(OmpDirectiveNameModifier)
|
||||
READ_FEATURE(OmpLinearClause)
|
||||
READ_FEATURE(OmpLinearClause::WithModifier)
|
||||
READ_FEATURE(OmpLinearClause::WithoutModifier)
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "FlangOmpReportVisitor.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Frontend/OpenMP/OMP.h"
|
||||
|
||||
namespace Fortran {
|
||||
namespace parser {
|
||||
@ -238,9 +239,9 @@ void OpenMPCounterVisitor::Post(const OmpScheduleClause::Kind &c) {
|
||||
clauseDetails +=
|
||||
"type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";";
|
||||
}
|
||||
void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) {
|
||||
void OpenMPCounterVisitor::Post(const OmpDirectiveNameModifier &c) {
|
||||
clauseDetails +=
|
||||
"name_modifier=" + std::string{OmpIfClause::EnumToString(c)} + ";";
|
||||
"name_modifier=" + llvm::omp::getOpenMPDirectiveName(c.v).str() + ";";
|
||||
}
|
||||
void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) {
|
||||
clauseDetails += "type=" + std::string{OmpCancelType::EnumToString(c)} + ";";
|
||||
|
@ -77,7 +77,7 @@ struct OpenMPCounterVisitor {
|
||||
void Post(const OmpTaskDependenceType::Value &c);
|
||||
void Post(const OmpMapType::Value &c);
|
||||
void Post(const OmpScheduleClause::Kind &c);
|
||||
void Post(const OmpIfClause::DirectiveNameModifier &c);
|
||||
void Post(const OmpDirectiveNameModifier &c);
|
||||
void Post(const OmpCancelType::Type &c);
|
||||
void Post(const OmpClause &c);
|
||||
void PostClauseCommon(const ClauseInfo &ci);
|
||||
|
@ -550,10 +550,13 @@ public:
|
||||
NODE(OmpFromClause, Modifier)
|
||||
NODE(parser, OmpExpectation)
|
||||
NODE_ENUM(OmpExpectation, Value)
|
||||
NODE(parser, OmpDirectiveNameModifier)
|
||||
NODE(parser, OmpIfClause)
|
||||
NODE_ENUM(OmpIfClause, DirectiveNameModifier)
|
||||
NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
|
||||
NODE(OmpIfClause, Modifier)
|
||||
NODE(parser, OmpLastprivateClause)
|
||||
NODE(OmpLastprivateClause, Modifier)
|
||||
NODE(parser, OmpLastprivateModifier)
|
||||
NODE_ENUM(OmpLastprivateModifier, Value)
|
||||
NODE(parser, OmpLinearClause)
|
||||
NODE(OmpLinearClause, WithModifier)
|
||||
NODE(OmpLinearClause, WithoutModifier)
|
||||
|
@ -3558,6 +3558,23 @@ struct OmpDeviceModifier {
|
||||
WRAPPER_CLASS_BOILERPLATE(OmpDeviceModifier, Value);
|
||||
};
|
||||
|
||||
// Ref: [5.2:72-73,230-323], in 4.5-5.1 it's scattered over individual
|
||||
// directives that allow the IF clause.
|
||||
//
|
||||
// directive-name-modifier ->
|
||||
// PARALLEL | TARGET | TARGET DATA |
|
||||
// TARGET ENTER DATA | TARGET EXIT DATA |
|
||||
// TARGET UPDATE | TASK | TASKLOOP | // since 4.5
|
||||
// CANCEL[*] | SIMD | // since 5.0
|
||||
// TEAMS // since 5.2
|
||||
//
|
||||
// [*] The IF clause is allowed on CANCEL in OpenMP 4.5, but only without
|
||||
// the directive-name-modifier. For the sake of uniformity CANCEL can be
|
||||
// considered a valid value in 4.5 as well.
|
||||
struct OmpDirectiveNameModifier {
|
||||
WRAPPER_CLASS_BOILERPLATE(OmpDirectiveNameModifier, llvm::omp::Directive);
|
||||
};
|
||||
|
||||
// Ref: [5.1:205-209], [5.2:166-168]
|
||||
//
|
||||
// motion-modifier ->
|
||||
@ -3581,6 +3598,15 @@ struct OmpIterator {
|
||||
WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
|
||||
};
|
||||
|
||||
// Ref: [5.0:288-290], [5.1:321-322], [5.2:115-117]
|
||||
//
|
||||
// lastprivate-modifier ->
|
||||
// CONDITIONAL // since 5.0
|
||||
struct OmpLastprivateModifier {
|
||||
ENUM_CLASS(Value, Conditional)
|
||||
WRAPPER_CLASS_BOILERPLATE(OmpLastprivateModifier, Value);
|
||||
};
|
||||
|
||||
// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
|
||||
//
|
||||
// linear-modifier ->
|
||||
@ -3913,12 +3939,16 @@ struct OmpGrainsizeClause {
|
||||
std::tuple<MODIFIERS(), ScalarIntExpr> t;
|
||||
};
|
||||
|
||||
// 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr)
|
||||
// Ref: [5.2:72-73], in 4.5-5.1 it's scattered over individual directives
|
||||
// that allow the IF clause.
|
||||
//
|
||||
// if-clause ->
|
||||
// IF([directive-name-modifier:]
|
||||
// scalar-logical-expression) // since 4.5
|
||||
struct OmpIfClause {
|
||||
TUPLE_CLASS_BOILERPLATE(OmpIfClause);
|
||||
ENUM_CLASS(DirectiveNameModifier, Parallel, Simd, Target, TargetData,
|
||||
TargetEnterData, TargetExitData, TargetUpdate, Task, Taskloop, Teams)
|
||||
std::tuple<std::optional<DirectiveNameModifier>, ScalarLogicalExpr> t;
|
||||
MODIFIER_BOILERPLATE(OmpDirectiveNameModifier);
|
||||
std::tuple<MODIFIERS(), ScalarLogicalExpr> t;
|
||||
};
|
||||
|
||||
// OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier:
|
||||
@ -3928,13 +3958,15 @@ struct OmpInReductionClause {
|
||||
std::tuple<OmpReductionIdentifier, OmpObjectList> t;
|
||||
};
|
||||
|
||||
// OMP 5.0 2.19.4.5 lastprivate-clause ->
|
||||
// LASTPRIVATE ([lastprivate-modifier :] list)
|
||||
// lastprivate-modifier -> CONDITIONAL
|
||||
// Ref: [4.5:199-201], [5.0:288-290], [5.1:321-322], [5.2:115-117]
|
||||
//
|
||||
// lastprivate-clause ->
|
||||
// LASTPRIVATE(list) | // since 4.5
|
||||
// LASTPRIVATE([lastprivate-modifier:] list) // since 5.0
|
||||
struct OmpLastprivateClause {
|
||||
TUPLE_CLASS_BOILERPLATE(OmpLastprivateClause);
|
||||
ENUM_CLASS(LastprivateModifier, Conditional);
|
||||
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
|
||||
MODIFIER_BOILERPLATE(OmpLastprivateModifier);
|
||||
std::tuple<MODIFIERS(), OmpObjectList> t;
|
||||
};
|
||||
|
||||
// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
|
||||
|
@ -74,8 +74,10 @@ DECLARE_DESCRIPTOR(parser::OmpAllocatorSimpleModifier);
|
||||
DECLARE_DESCRIPTOR(parser::OmpChunkModifier);
|
||||
DECLARE_DESCRIPTOR(parser::OmpDependenceType);
|
||||
DECLARE_DESCRIPTOR(parser::OmpDeviceModifier);
|
||||
DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier);
|
||||
DECLARE_DESCRIPTOR(parser::OmpExpectation);
|
||||
DECLARE_DESCRIPTOR(parser::OmpIterator);
|
||||
DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier);
|
||||
DECLARE_DESCRIPTOR(parser::OmpLinearModifier);
|
||||
DECLARE_DESCRIPTOR(parser::OmpMapper);
|
||||
DECLARE_DESCRIPTOR(parser::OmpMapType);
|
||||
|
@ -825,27 +825,13 @@ Holds make(const parser::OmpClause::Holds &inp,
|
||||
If make(const parser::OmpClause::If &inp,
|
||||
semantics::SemanticsContext &semaCtx) {
|
||||
// inp.v -> parser::OmpIfClause
|
||||
using wrapped = parser::OmpIfClause;
|
||||
|
||||
CLAUSET_ENUM_CONVERT( //
|
||||
convert, wrapped::DirectiveNameModifier, llvm::omp::Directive,
|
||||
// clang-format off
|
||||
MS(Parallel, OMPD_parallel)
|
||||
MS(Simd, OMPD_simd)
|
||||
MS(Target, OMPD_target)
|
||||
MS(TargetData, OMPD_target_data)
|
||||
MS(TargetEnterData, OMPD_target_enter_data)
|
||||
MS(TargetExitData, OMPD_target_exit_data)
|
||||
MS(TargetUpdate, OMPD_target_update)
|
||||
MS(Task, OMPD_task)
|
||||
MS(Taskloop, OMPD_taskloop)
|
||||
MS(Teams, OMPD_teams)
|
||||
// clang-format on
|
||||
);
|
||||
auto &t0 = std::get<std::optional<wrapped::DirectiveNameModifier>>(inp.v.t);
|
||||
auto &mods = semantics::OmpGetModifiers(inp.v);
|
||||
auto *m0 =
|
||||
semantics::OmpGetUniqueModifier<parser::OmpDirectiveNameModifier>(mods);
|
||||
auto &t1 = std::get<parser::ScalarLogicalExpr>(inp.v.t);
|
||||
return If{{/*DirectiveNameModifier=*/maybeApply(convert, t0),
|
||||
/*IfExpression=*/makeExpr(t1, semaCtx)}};
|
||||
return If{
|
||||
{/*DirectiveNameModifier=*/maybeApplyToV([](auto &&s) { return s; }, m0),
|
||||
/*IfExpression=*/makeExpr(t1, semaCtx)}};
|
||||
}
|
||||
|
||||
// Inbranch: empty
|
||||
@ -889,20 +875,20 @@ IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp,
|
||||
Lastprivate make(const parser::OmpClause::Lastprivate &inp,
|
||||
semantics::SemanticsContext &semaCtx) {
|
||||
// inp.v -> parser::OmpLastprivateClause
|
||||
using wrapped = parser::OmpLastprivateClause;
|
||||
|
||||
CLAUSET_ENUM_CONVERT( //
|
||||
convert, parser::OmpLastprivateClause::LastprivateModifier,
|
||||
convert, parser::OmpLastprivateModifier::Value,
|
||||
Lastprivate::LastprivateModifier,
|
||||
// clang-format off
|
||||
MS(Conditional, Conditional)
|
||||
// clang-format on
|
||||
);
|
||||
|
||||
auto &t0 = std::get<std::optional<wrapped::LastprivateModifier>>(inp.v.t);
|
||||
auto &mods = semantics::OmpGetModifiers(inp.v);
|
||||
auto *m0 =
|
||||
semantics::OmpGetUniqueModifier<parser::OmpLastprivateModifier>(mods);
|
||||
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
|
||||
|
||||
return Lastprivate{{/*LastprivateModifier=*/maybeApply(convert, t0),
|
||||
return Lastprivate{{/*LastprivateModifier=*/maybeApplyToV(convert, m0),
|
||||
/*List=*/makeObjects(t1, semaCtx)}};
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ add_flang_library(FortranParser
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
FrontendOpenACC
|
||||
FrontendOpenMP
|
||||
|
||||
DEPENDS
|
||||
omp_gen
|
||||
|
@ -16,6 +16,10 @@
|
||||
#include "token-parsers.h"
|
||||
#include "type-parser-implementation.h"
|
||||
#include "flang/Parser/parse-tree.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Frontend/OpenMP/OMP.h"
|
||||
|
||||
// OpenMP Directives and Clauses
|
||||
namespace Fortran::parser {
|
||||
@ -23,6 +27,47 @@ namespace Fortran::parser {
|
||||
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
|
||||
constexpr auto endOmpLine = space >> endOfLine;
|
||||
|
||||
/// Parse OpenMP directive name (this includes compound directives).
|
||||
struct OmpDirectiveNameParser {
|
||||
using resultType = llvm::omp::Directive;
|
||||
using Token = TokenStringMatch<false, false>;
|
||||
|
||||
std::optional<resultType> Parse(ParseState &state) const {
|
||||
for (const NameWithId &nid : directives()) {
|
||||
if (attempt(Token(nid.first.data())).Parse(state)) {
|
||||
return nid.second;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
using NameWithId = std::pair<std::string, llvm::omp::Directive>;
|
||||
|
||||
llvm::iterator_range<const NameWithId *> directives() const;
|
||||
void initTokens(NameWithId *) const;
|
||||
};
|
||||
|
||||
llvm::iterator_range<const OmpDirectiveNameParser::NameWithId *>
|
||||
OmpDirectiveNameParser::directives() const {
|
||||
static NameWithId table[llvm::omp::Directive_enumSize];
|
||||
[[maybe_unused]] static bool init = (initTokens(table), true);
|
||||
return llvm::make_range(std::cbegin(table), std::cend(table));
|
||||
}
|
||||
|
||||
void OmpDirectiveNameParser::initTokens(NameWithId *table) const {
|
||||
for (size_t i{0}, e{llvm::omp::Directive_enumSize}; i != e; ++i) {
|
||||
auto id{static_cast<llvm::omp::Directive>(i)};
|
||||
llvm::StringRef name{llvm::omp::getOpenMPDirectiveName(id)};
|
||||
table[i] = std::make_pair(name.str(), id);
|
||||
}
|
||||
// Sort the table with respect to the directive name length in a descending
|
||||
// order. This is to make sure that longer names are tried first, before
|
||||
// any potential prefix (e.g. "target update" before "target").
|
||||
std::sort(table, table + llvm::omp::Directive_enumSize,
|
||||
[](auto &a, auto &b) { return a.first.size() > b.first.size(); });
|
||||
}
|
||||
|
||||
template <typename Clause, typename Separator> struct ModifierList {
|
||||
constexpr ModifierList(Separator sep) : sep_(sep) {}
|
||||
constexpr ModifierList(const ModifierList &) = default;
|
||||
@ -136,6 +181,9 @@ TYPE_PARSER(construct<OmpIterator>( //
|
||||
"ITERATOR" >>
|
||||
parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{})))))
|
||||
|
||||
TYPE_PARSER(construct<OmpLastprivateModifier>(
|
||||
"CONDITIONAL" >> pure(OmpLastprivateModifier::Value::Conditional)))
|
||||
|
||||
// 2.15.3.7 LINEAR (linear-list: linear-step)
|
||||
// linear-list -> list | modifier(list)
|
||||
// linear-modifier -> REF | VAL | UVAL
|
||||
@ -232,6 +280,11 @@ TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
|
||||
TYPE_PARSER(sourced(
|
||||
construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{})))
|
||||
|
||||
TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
|
||||
|
||||
TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>(
|
||||
Parser<OmpLastprivateModifier>{})))
|
||||
|
||||
TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
|
||||
sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) ||
|
||||
construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
|
||||
@ -345,22 +398,7 @@ TYPE_PARSER(construct<OmpDeviceTypeClause>(
|
||||
|
||||
// 2.12 IF (directive-name-modifier: scalar-logical-expr)
|
||||
TYPE_PARSER(construct<OmpIfClause>(
|
||||
maybe(
|
||||
("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
|
||||
"SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) ||
|
||||
"TARGET ENTER DATA" >>
|
||||
pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
|
||||
"TARGET EXIT DATA" >>
|
||||
pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
|
||||
"TARGET DATA" >>
|
||||
pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
|
||||
"TARGET UPDATE" >>
|
||||
pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
|
||||
"TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
|
||||
"TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) ||
|
||||
"TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
|
||||
"TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) /
|
||||
":"),
|
||||
maybe(nonemptyList(Parser<OmpIfClause::Modifier>{}) / ":"),
|
||||
scalarLogicalExpr))
|
||||
|
||||
TYPE_PARSER(construct<OmpReductionClause>(
|
||||
@ -460,8 +498,7 @@ TYPE_PARSER(
|
||||
|
||||
// OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list)
|
||||
TYPE_PARSER(construct<OmpLastprivateClause>(
|
||||
maybe("CONDITIONAL" >>
|
||||
pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"),
|
||||
maybe(nonemptyList(Parser<OmpLastprivateClause::Modifier>{}) / ":"),
|
||||
Parser<OmpObjectList>{}))
|
||||
|
||||
// OMP 5.2 11.7.1 BIND ( PARALLEL | TEAMS | THREAD )
|
||||
|
@ -2074,6 +2074,9 @@ public:
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
void Unparse(const OmpDirectiveNameModifier &x) {
|
||||
Word(llvm::omp::getOpenMPDirectiveName(x.v));
|
||||
}
|
||||
void Unparse(const OmpIteratorSpecifier &x) {
|
||||
Walk(std::get<TypeDeclarationStmt>(x.t));
|
||||
Put(" = ");
|
||||
@ -2090,9 +2093,8 @@ public:
|
||||
Put(")");
|
||||
}
|
||||
void Unparse(const OmpLastprivateClause &x) {
|
||||
Walk(
|
||||
std::get<std::optional<OmpLastprivateClause::LastprivateModifier>>(x.t),
|
||||
":");
|
||||
using Modifier = OmpLastprivateClause::Modifier;
|
||||
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
|
||||
Walk(std::get<OmpObjectList>(x.t));
|
||||
}
|
||||
void Unparse(const OmpMapClause &x) {
|
||||
@ -2127,7 +2129,8 @@ public:
|
||||
Walk(std::get<OmpObjectList>(x.t));
|
||||
}
|
||||
void Unparse(const OmpIfClause &x) {
|
||||
Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t), ":");
|
||||
using Modifier = OmpIfClause::Modifier;
|
||||
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
|
||||
Walk(std::get<ScalarLogicalExpr>(x.t));
|
||||
}
|
||||
void Unparse(const OmpLinearClause::WithoutModifier &x) {
|
||||
@ -2837,8 +2840,7 @@ public:
|
||||
WALK_NESTED_ENUM(OmpDefaultClause, DataSharingAttribute) // OMP default
|
||||
WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP defaultmap
|
||||
WALK_NESTED_ENUM(OmpVariableCategory, Value) // OMP variable-category
|
||||
WALK_NESTED_ENUM(
|
||||
OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
|
||||
WALK_NESTED_ENUM(OmpLastprivateModifier, Value) // OMP lastprivate-modifier
|
||||
WALK_NESTED_ENUM(OmpChunkModifier, Value) // OMP chunk-modifier
|
||||
WALK_NESTED_ENUM(OmpLinearModifier, Value) // OMP linear-modifier
|
||||
WALK_NESTED_ENUM(OmpOrderingModifier, Value) // OMP ordering-modifier
|
||||
@ -2849,7 +2851,6 @@ public:
|
||||
OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type
|
||||
WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier
|
||||
WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation
|
||||
WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
|
||||
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
|
||||
WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering
|
||||
WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier
|
||||
|
@ -3455,36 +3455,82 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
|
||||
CheckAllowedClause(llvm::omp::Clause::OMPC_if);
|
||||
using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier;
|
||||
// TODO Check that, when multiple 'if' clauses are applied to a combined
|
||||
// construct, at most one of them applies to each directive.
|
||||
static std::unordered_map<dirNameModifier, OmpDirectiveSet>
|
||||
dirNameModifierMap{{dirNameModifier::Parallel, llvm::omp::allParallelSet},
|
||||
{dirNameModifier::Simd, llvm::omp::allSimdSet},
|
||||
{dirNameModifier::Target, llvm::omp::allTargetSet},
|
||||
{dirNameModifier::TargetData,
|
||||
{llvm::omp::Directive::OMPD_target_data}},
|
||||
{dirNameModifier::TargetEnterData,
|
||||
{llvm::omp::Directive::OMPD_target_enter_data}},
|
||||
{dirNameModifier::TargetExitData,
|
||||
{llvm::omp::Directive::OMPD_target_exit_data}},
|
||||
{dirNameModifier::TargetUpdate,
|
||||
{llvm::omp::Directive::OMPD_target_update}},
|
||||
{dirNameModifier::Task, {llvm::omp::Directive::OMPD_task}},
|
||||
{dirNameModifier::Taskloop, llvm::omp::allTaskloopSet},
|
||||
{dirNameModifier::Teams, llvm::omp::allTeamsSet}};
|
||||
if (const auto &directiveName{
|
||||
std::get<std::optional<dirNameModifier>>(x.v.t)}) {
|
||||
auto search{dirNameModifierMap.find(*directiveName)};
|
||||
if (search == dirNameModifierMap.end() ||
|
||||
!search->second.test(GetContext().directive)) {
|
||||
context_
|
||||
.Say(GetContext().clauseSource,
|
||||
"Unmatched directive name modifier %s on the IF clause"_err_en_US,
|
||||
parser::ToUpperCaseLetters(
|
||||
parser::OmpIfClause::EnumToString(*directiveName)))
|
||||
.Attach(
|
||||
GetContext().directiveSource, "Cannot apply to directive"_en_US);
|
||||
unsigned version{context_.langOptions().OpenMPVersion};
|
||||
llvm::omp::Directive dir{GetContext().directive};
|
||||
|
||||
auto isConstituent{[](llvm::omp::Directive dir, llvm::omp::Directive part) {
|
||||
using namespace llvm::omp;
|
||||
llvm::ArrayRef<Directive> dirLeafs{getLeafConstructsOrSelf(dir)};
|
||||
llvm::ArrayRef<Directive> partLeafs{getLeafConstructsOrSelf(part)};
|
||||
// Maybe it's sufficient to check if every leaf of `part` is also a leaf
|
||||
// of `dir`, but to be safe check if `partLeafs` is a sub-sequence of
|
||||
// `dirLeafs`.
|
||||
size_t dirSize{dirLeafs.size()}, partSize{partLeafs.size()};
|
||||
// Find the first leaf from `part` in `dir`.
|
||||
if (auto first = llvm::find(dirLeafs, partLeafs.front());
|
||||
first != dirLeafs.end()) {
|
||||
// A leaf can only appear once in a compound directive, so if `part`
|
||||
// is a subsequence of `dir`, it must start here.
|
||||
size_t firstPos{
|
||||
static_cast<size_t>(std::distance(dirLeafs.begin(), first))};
|
||||
llvm::ArrayRef<Directive> subSeq{
|
||||
first, std::min<size_t>(dirSize - firstPos, partSize)};
|
||||
return subSeq == partLeafs;
|
||||
}
|
||||
return false;
|
||||
}};
|
||||
|
||||
if (OmpVerifyModifiers(
|
||||
x.v, llvm::omp::OMPC_if, GetContext().clauseSource, context_)) {
|
||||
auto &modifiers{OmpGetModifiers(x.v)};
|
||||
if (auto *dnm{OmpGetUniqueModifier<parser::OmpDirectiveNameModifier>(
|
||||
modifiers)}) {
|
||||
llvm::omp::Directive sub{dnm->v};
|
||||
std::string subName{parser::ToUpperCaseLetters(
|
||||
llvm::omp::getOpenMPDirectiveName(sub).str())};
|
||||
std::string dirName{parser::ToUpperCaseLetters(
|
||||
llvm::omp::getOpenMPDirectiveName(dir).str())};
|
||||
|
||||
parser::CharBlock modifierSource{OmpGetModifierSource(modifiers, dnm)};
|
||||
auto desc{OmpGetDescriptor<parser::OmpDirectiveNameModifier>()};
|
||||
std::string modName{desc.name.str()};
|
||||
|
||||
if (!isConstituent(dir, sub)) {
|
||||
context_
|
||||
.Say(modifierSource,
|
||||
"%s is not a constituent of the %s directive"_err_en_US,
|
||||
subName, dirName)
|
||||
.Attach(GetContext().directiveSource,
|
||||
"Cannot apply to directive"_en_US);
|
||||
} else {
|
||||
static llvm::omp::Directive valid45[]{
|
||||
llvm::omp::OMPD_cancel, //
|
||||
llvm::omp::OMPD_parallel, //
|
||||
/* OMP 5.0+ also allows OMPD_simd */
|
||||
llvm::omp::OMPD_target, //
|
||||
llvm::omp::OMPD_target_data, //
|
||||
llvm::omp::OMPD_target_enter_data, //
|
||||
llvm::omp::OMPD_target_exit_data, //
|
||||
llvm::omp::OMPD_target_update, //
|
||||
llvm::omp::OMPD_task, //
|
||||
llvm::omp::OMPD_taskloop, //
|
||||
/* OMP 5.2+ also allows OMPD_teams */
|
||||
};
|
||||
if (version < 50 && sub == llvm::omp::OMPD_simd) {
|
||||
context_.Say(modifierSource,
|
||||
"%s is not allowed as '%s' in %s, %s"_warn_en_US, subName,
|
||||
modName, ThisVersion(version), TryVersion(50));
|
||||
} else if (version < 52 && sub == llvm::omp::OMPD_teams) {
|
||||
context_.Say(modifierSource,
|
||||
"%s is not allowed as '%s' in %s, %s"_warn_en_US, subName,
|
||||
modName, ThisVersion(version), TryVersion(52));
|
||||
} else if (!llvm::is_contained(valid45, sub) &&
|
||||
sub != llvm::omp::OMPD_simd && sub != llvm::omp::OMPD_teams) {
|
||||
context_.Say(modifierSource,
|
||||
"%s is not allowed as '%s' in %s"_err_en_US, subName, modName,
|
||||
ThisVersion(version));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3884,20 +3930,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
|
||||
CheckPrivateSymbolsInOuterCxt(
|
||||
currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_lastprivate);
|
||||
|
||||
using LastprivateModifier = parser::OmpLastprivateClause::LastprivateModifier;
|
||||
const auto &maybeMod{std::get<std::optional<LastprivateModifier>>(x.v.t)};
|
||||
if (maybeMod) {
|
||||
unsigned version{context_.langOptions().OpenMPVersion};
|
||||
unsigned allowedInVersion = 50;
|
||||
if (version < allowedInVersion) {
|
||||
std::string thisVersion{
|
||||
std::to_string(version / 10) + "." + std::to_string(version % 10)};
|
||||
context_.Say(GetContext().clauseSource,
|
||||
"LASTPRIVATE clause with CONDITIONAL modifier is not "
|
||||
"allowed in %s, %s"_err_en_US,
|
||||
ThisVersion(version), TryVersion(allowedInVersion));
|
||||
}
|
||||
}
|
||||
OmpVerifyModifiers(
|
||||
x.v, llvm::omp::OMPC_lastprivate, GetContext().clauseSource, context_);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
|
||||
|
@ -190,6 +190,23 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeviceModifier>() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
template <>
|
||||
const OmpModifierDescriptor &
|
||||
OmpGetDescriptor<parser::OmpDirectiveNameModifier>() {
|
||||
static const OmpModifierDescriptor desc{
|
||||
/*name=*/"directive-name-modifier",
|
||||
/*props=*/
|
||||
{
|
||||
{45, {OmpProperty::Unique}},
|
||||
},
|
||||
/*clauses=*/
|
||||
{
|
||||
{45, {Clause::OMPC_if}},
|
||||
},
|
||||
};
|
||||
return desc;
|
||||
}
|
||||
|
||||
template <>
|
||||
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {
|
||||
static const OmpModifierDescriptor desc{
|
||||
@ -225,6 +242,23 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
template <>
|
||||
const OmpModifierDescriptor &
|
||||
OmpGetDescriptor<parser::OmpLastprivateModifier>() {
|
||||
static const OmpModifierDescriptor desc{
|
||||
/*name=*/"lastprivate-modifier",
|
||||
/*props=*/
|
||||
{
|
||||
{50, {OmpProperty::Unique}},
|
||||
},
|
||||
/*clauses=*/
|
||||
{
|
||||
{50, {Clause::OMPC_lastprivate}},
|
||||
},
|
||||
};
|
||||
return desc;
|
||||
}
|
||||
|
||||
template <>
|
||||
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {
|
||||
static const OmpModifierDescriptor desc{
|
||||
|
@ -10,50 +10,50 @@ program if_unparse
|
||||
!$omp target update if(cond)
|
||||
|
||||
! CHECK: !$OMP TARGET UPDATE
|
||||
! CHECK-SAME: IF(TARGETUPDATE:cond)
|
||||
! CHECK-SAME: IF(TARGET UPDATE: cond)
|
||||
!$omp target update if(target update: cond)
|
||||
|
||||
! CHECK: !$OMP TARGET UPDATE
|
||||
! CHECK-SAME: IF(TARGETUPDATE:cond)
|
||||
! CHECK-SAME: IF(TARGET UPDATE: cond)
|
||||
!$omp target update if(targetupdate: cond)
|
||||
|
||||
! CHECK: !$OMP TARGET ENTER DATA
|
||||
! CHECK-SAME: IF(TARGETENTERDATA:cond)
|
||||
! CHECK-SAME: IF(TARGET ENTER DATA: cond)
|
||||
!$omp target enter data map(to: i) if(target enter data: cond)
|
||||
|
||||
! CHECK: !$OMP TARGET EXIT DATA
|
||||
! CHECK-SAME: IF(TARGETEXITDATA:cond)
|
||||
! CHECK-SAME: IF(TARGET EXIT DATA: cond)
|
||||
!$omp target exit data map(from: i) if(target exit data: cond)
|
||||
|
||||
! CHECK: !$OMP TARGET DATA
|
||||
! CHECK-SAME: IF(TARGETDATA:cond)
|
||||
! CHECK-SAME: IF(TARGET DATA: cond)
|
||||
!$omp target data map(tofrom: i) if(target data: cond)
|
||||
!$omp end target data
|
||||
|
||||
! CHECK: !$OMP TARGET
|
||||
! CHECK-SAME: IF(TARGET:cond)
|
||||
! CHECK-SAME: IF(TARGET: cond)
|
||||
!$omp target if(target: cond)
|
||||
!$omp end target
|
||||
|
||||
! CHECK: !$OMP TEAMS
|
||||
! CHECK-SAME: IF(TEAMS:cond)
|
||||
! CHECK-SAME: IF(TEAMS: cond)
|
||||
!$omp teams if(teams: cond)
|
||||
!$omp end teams
|
||||
|
||||
! CHECK: !$OMP PARALLEL DO SIMD
|
||||
! CHECK-SAME: IF(PARALLEL:i<10) IF(SIMD:.FALSE.)
|
||||
! CHECK-SAME: IF(PARALLEL: i<10) IF(SIMD: .FALSE.)
|
||||
!$omp parallel do simd if(parallel: i < 10) if(simd: .false.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
!$omp end parallel do simd
|
||||
|
||||
! CHECK: !$OMP TASK
|
||||
! CHECK-SAME: IF(TASK:cond)
|
||||
! CHECK-SAME: IF(TASK: cond)
|
||||
!$omp task if(task: cond)
|
||||
!$omp end task
|
||||
|
||||
! CHECK: !$OMP TASKLOOP
|
||||
! CHECK-SAME: IF(TASKLOOP:cond)
|
||||
! CHECK-SAME: IF(TASKLOOP: cond)
|
||||
!$omp taskloop if(taskloop: cond)
|
||||
do i = 1, 10
|
||||
end do
|
||||
|
@ -1,4 +1,4 @@
|
||||
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck %s
|
||||
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck %s
|
||||
|
||||
program openmp_parse_if
|
||||
logical :: cond
|
||||
@ -11,34 +11,34 @@ program openmp_parse_if
|
||||
|
||||
! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
|
||||
! CHECK-NEXT: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = TargetUpdate
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target update
|
||||
!$omp target update if(target update: cond) to(i)
|
||||
|
||||
! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target enter data
|
||||
! CHECK: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = TargetEnterData
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target enter data
|
||||
!$omp target enter data map(to: i) if(target enter data: cond)
|
||||
|
||||
! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target exit data
|
||||
! CHECK: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = TargetExitData
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target exit data
|
||||
!$omp target exit data map(from: i) if(target exit data: cond)
|
||||
|
||||
! CHECK: OmpBlockDirective -> llvm::omp::Directive = target data
|
||||
! CHECK: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = TargetData
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target data
|
||||
!$omp target data map(tofrom: i) if(target data: cond)
|
||||
!$omp end target data
|
||||
|
||||
! CHECK: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do simd
|
||||
! CHECK: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = Target
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target
|
||||
! CHECK: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = Teams
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = teams
|
||||
! CHECK: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = Parallel
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = parallel
|
||||
! CHECK: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = Simd
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = simd
|
||||
!$omp target teams distribute parallel do simd if(target: cond) &
|
||||
!$omp& if(teams: cond) if(parallel: cond) if(simd: cond)
|
||||
do i = 1, 10
|
||||
@ -47,13 +47,13 @@ program openmp_parse_if
|
||||
|
||||
! CHECK: OmpBlockDirective -> llvm::omp::Directive = task
|
||||
! CHECK-NEXT: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = Task
|
||||
! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = task
|
||||
!$omp task if(task: cond)
|
||||
!$omp end task
|
||||
|
||||
! CHECK: OmpLoopDirective -> llvm::omp::Directive = taskloop
|
||||
! CHECK-NEXT: OmpClause -> If -> OmpIfClause
|
||||
! CHECK-NEXT: DirectiveNameModifier = Taskloop
|
||||
! CHECK-NEXT: DirectiveNameModifier -> llvm::omp::Directive = taskloop
|
||||
!$omp taskloop if(taskloop: cond)
|
||||
do i = 1, 10
|
||||
end do
|
||||
|
@ -39,7 +39,7 @@ end
|
||||
!UNPARSE: SUBROUTINE foo2
|
||||
!UNPARSE: INTEGER x, i
|
||||
!UNPARSE: x=1_4
|
||||
!UNPARSE: !$OMP PARALLEL DO LASTPRIVATE(CONDITIONAL:x)
|
||||
!UNPARSE: !$OMP PARALLEL DO LASTPRIVATE(CONDITIONAL: x)
|
||||
!UNPARSE: DO i=1_4,100_4
|
||||
!UNPARSE: x=x+1_4
|
||||
!UNPARSE: END DO
|
||||
@ -49,6 +49,6 @@ end
|
||||
!PARSE-TREE: Name = 'foo2'
|
||||
!PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = parallel do
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Lastprivate -> OmpLastprivateClause
|
||||
!PARSE-TREE: LastprivateModifier = Conditional
|
||||
!PARSE-TREE: Modifier -> OmpLastprivateModifier -> Value = Conditional
|
||||
!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
|
||||
!PARSE-TREE: EndSubroutineStmt
|
||||
|
@ -241,7 +241,7 @@ use omp_lib
|
||||
enddo
|
||||
!$omp end parallel do simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the PARALLEL DO directive
|
||||
!$omp parallel do if(target:a>1.)
|
||||
do i = 1, N
|
||||
enddo
|
||||
@ -532,7 +532,7 @@ use omp_lib
|
||||
a = 1.
|
||||
!$omp end task
|
||||
|
||||
!ERROR: Unmatched directive name modifier TASKLOOP on the IF clause
|
||||
!ERROR: TASKLOOP is not a constituent of the TASK directive
|
||||
!$omp task private(a) if(taskloop:a.eq.1)
|
||||
a = 1.
|
||||
!$omp end task
|
||||
|
@ -18,7 +18,7 @@ program main
|
||||
end do
|
||||
!$omp end distribute parallel do
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the DISTRIBUTE PARALLEL DO directive
|
||||
!$omp distribute parallel do if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -45,7 +45,7 @@ program main
|
||||
end do
|
||||
!$omp end distribute parallel do simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the DISTRIBUTE PARALLEL DO SIMD directive
|
||||
!$omp distribute parallel do simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -66,7 +66,7 @@ program main
|
||||
end do
|
||||
!$omp end distribute simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the DISTRIBUTE SIMD directive
|
||||
!$omp distribute simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -92,7 +92,7 @@ program main
|
||||
end do
|
||||
!$omp end do simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the DO SIMD directive
|
||||
!$omp do simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -113,7 +113,7 @@ program main
|
||||
!$omp parallel if(parallel: .true.)
|
||||
!$omp end parallel
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the PARALLEL directive
|
||||
!$omp parallel if(target: .true.)
|
||||
!$omp end parallel
|
||||
|
||||
@ -134,7 +134,7 @@ program main
|
||||
end do
|
||||
!$omp end parallel do
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the PARALLEL DO directive
|
||||
!$omp parallel do if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -159,7 +159,7 @@ program main
|
||||
end do
|
||||
!$omp end parallel do simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the PARALLEL DO SIMD directive
|
||||
!$omp parallel do simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -174,7 +174,7 @@ program main
|
||||
!$omp parallel sections if(parallel: .true.)
|
||||
!$omp end parallel sections
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the PARALLEL SECTIONS directive
|
||||
!$omp parallel sections if(target: .true.)
|
||||
!$omp end parallel sections
|
||||
|
||||
@ -191,7 +191,7 @@ program main
|
||||
!$omp parallel workshare if(parallel: .true.)
|
||||
!$omp end parallel workshare
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the PARALLEL WORKSHARE directive
|
||||
!$omp parallel workshare if(target: .true.)
|
||||
!$omp end parallel workshare
|
||||
|
||||
@ -212,7 +212,7 @@ program main
|
||||
end do
|
||||
!$omp end simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the SIMD directive
|
||||
!$omp simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -233,7 +233,7 @@ program main
|
||||
!$omp target if(target: .true.)
|
||||
!$omp end target
|
||||
|
||||
!ERROR: Unmatched directive name modifier PARALLEL on the IF clause
|
||||
!ERROR: PARALLEL is not a constituent of the TARGET directive
|
||||
!$omp target if(parallel: .true.)
|
||||
!$omp end target
|
||||
|
||||
@ -250,7 +250,7 @@ program main
|
||||
!$omp target data map(tofrom: i) if(target data: .true.)
|
||||
!$omp end target data
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TARGET DATA directive
|
||||
!$omp target data map(tofrom: i) if(target: .true.)
|
||||
!$omp end target data
|
||||
|
||||
@ -265,7 +265,7 @@ program main
|
||||
|
||||
!$omp target enter data map(to: i) if(target enter data: .true.)
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TARGET ENTER DATA directive
|
||||
!$omp target enter data map(to: i) if(target: .true.)
|
||||
|
||||
!ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive
|
||||
@ -278,7 +278,7 @@ program main
|
||||
|
||||
!$omp target exit data map(from: i) if(target exit data: .true.)
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TARGET EXIT DATA directive
|
||||
!$omp target exit data map(from: i) if(target: .true.)
|
||||
|
||||
!ERROR: At most one IF clause can appear on the TARGET EXIT DATA directive
|
||||
@ -293,7 +293,7 @@ program main
|
||||
!$omp target parallel if(target: .true.) if(parallel: .false.)
|
||||
!$omp end target parallel
|
||||
|
||||
!ERROR: Unmatched directive name modifier SIMD on the IF clause
|
||||
!ERROR: SIMD is not a constituent of the TARGET PARALLEL directive
|
||||
!$omp target parallel if(simd: .true.)
|
||||
!$omp end target parallel
|
||||
|
||||
@ -310,7 +310,7 @@ program main
|
||||
end do
|
||||
!$omp end target parallel do
|
||||
|
||||
!ERROR: Unmatched directive name modifier SIMD on the IF clause
|
||||
!ERROR: SIMD is not a constituent of the TARGET PARALLEL DO directive
|
||||
!$omp target parallel do if(simd: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -330,7 +330,7 @@ program main
|
||||
end do
|
||||
!$omp end target parallel do simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TEAMS on the IF clause
|
||||
!ERROR: TEAMS is not a constituent of the TARGET PARALLEL DO SIMD directive
|
||||
!$omp target parallel do simd if(teams: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -349,7 +349,7 @@ program main
|
||||
end do
|
||||
!$omp end target simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier PARALLEL on the IF clause
|
||||
!ERROR: PARALLEL is not a constituent of the TARGET SIMD directive
|
||||
!$omp target simd if(parallel: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -364,7 +364,7 @@ program main
|
||||
!$omp target teams if(target: .true.) if(teams: .false.)
|
||||
!$omp end target teams
|
||||
|
||||
!ERROR: Unmatched directive name modifier PARALLEL on the IF clause
|
||||
!ERROR: PARALLEL is not a constituent of the TARGET TEAMS directive
|
||||
!$omp target teams if(parallel: .true.)
|
||||
!$omp end target teams
|
||||
|
||||
@ -381,7 +381,7 @@ program main
|
||||
end do
|
||||
!$omp end target teams distribute
|
||||
|
||||
!ERROR: Unmatched directive name modifier PARALLEL on the IF clause
|
||||
!ERROR: PARALLEL is not a constituent of the TARGET TEAMS DISTRIBUTE directive
|
||||
!$omp target teams distribute if(parallel: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -401,7 +401,7 @@ program main
|
||||
end do
|
||||
!$omp end target teams distribute parallel do
|
||||
|
||||
!ERROR: Unmatched directive name modifier SIMD on the IF clause
|
||||
!ERROR: SIMD is not a constituent of the TARGET TEAMS DISTRIBUTE PARALLEL DO directive
|
||||
!$omp target teams distribute parallel do if(simd: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -422,7 +422,7 @@ program main
|
||||
end do
|
||||
!$omp end target teams distribute parallel do simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TASK on the IF clause
|
||||
!ERROR: TASK is not a constituent of the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive
|
||||
!$omp target teams distribute parallel do simd if(task: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -442,7 +442,7 @@ program main
|
||||
end do
|
||||
!$omp end target teams distribute simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier PARALLEL on the IF clause
|
||||
!ERROR: PARALLEL is not a constituent of the TARGET TEAMS DISTRIBUTE SIMD directive
|
||||
!$omp target teams distribute simd if(parallel: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -455,7 +455,7 @@ program main
|
||||
|
||||
!$omp target update to(i) if(target update: .true.)
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TARGET UPDATE directive
|
||||
!$omp target update to(i) if(target: .true.)
|
||||
|
||||
!ERROR: At most one IF clause can appear on the TARGET UPDATE directive
|
||||
@ -470,7 +470,7 @@ program main
|
||||
!$omp task if(task: .true.)
|
||||
!$omp end task
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TASK directive
|
||||
!$omp task if(target: .true.)
|
||||
!$omp end task
|
||||
|
||||
@ -491,7 +491,7 @@ program main
|
||||
end do
|
||||
!$omp end taskloop
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TASKLOOP directive
|
||||
!$omp taskloop if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -516,7 +516,7 @@ program main
|
||||
end do
|
||||
!$omp end taskloop simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TASKLOOP SIMD directive
|
||||
!$omp taskloop simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -531,7 +531,7 @@ program main
|
||||
!$omp teams if(teams: .true.)
|
||||
!$omp end teams
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TEAMS directive
|
||||
!$omp teams if(target: .true.)
|
||||
!$omp end teams
|
||||
|
||||
@ -552,7 +552,7 @@ program main
|
||||
end do
|
||||
!$omp end teams distribute
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE directive
|
||||
!$omp teams distribute if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -577,7 +577,7 @@ program main
|
||||
end do
|
||||
!$omp end teams distribute parallel do
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE PARALLEL DO directive
|
||||
!$omp teams distribute parallel do if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -597,7 +597,7 @@ program main
|
||||
end do
|
||||
!$omp end teams distribute parallel do simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE PARALLEL DO SIMD directive
|
||||
!$omp teams distribute parallel do simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
@ -616,7 +616,7 @@ program main
|
||||
end do
|
||||
!$omp end teams distribute simd
|
||||
|
||||
!ERROR: Unmatched directive name modifier TARGET on the IF clause
|
||||
!ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE SIMD directive
|
||||
!$omp teams distribute simd if(target: .true.)
|
||||
do i = 1, 10
|
||||
end do
|
||||
|
Loading…
x
Reference in New Issue
Block a user