[flang] [OpenMP] parse tree changes for standalone directives (flang-compiler/f18#627)
* [OpenMP] parse tree changes for standalone directives 1. Put all standalone directives except FLUSH, CANCEL, and CANCELLATION POINT into one `OpenMPSimpleStandaloneConstruct` (for no-clause directive, validity checks will be deferred to Semantics). A top-level class will include all the standalone directive nodes. This simplies the logic a lot. 2. All the standalone directives now have their own source provenance for directive name itself. 3. Change check-omp-structure.* to avoid assertions 4. Add basic tests for standalone directives, more will be added during the clause validity checks in Semantics * Resolve !$OMP ORDERED ambiguity by attempting block construct first - Peter Original-commit: flang-compiler/f18@a77aa7ed84 Reviewed-on: https://github.com/flang-compiler/f18/pull/627
This commit is contained in:
parent
fb30d812e7
commit
c4e13f6be8
|
@ -512,8 +512,8 @@ public:
|
|||
NODE(parser, OmpScheduleModifierType)
|
||||
NODE_ENUM(parser::OmpScheduleModifierType, ModType)
|
||||
NODE(parser, OmpSection)
|
||||
NODE(parser, OmpStandaloneDirective)
|
||||
NODE_ENUM(parser::OmpStandaloneDirective, Directive)
|
||||
NODE(parser, OmpSimpleStandaloneDirective)
|
||||
NODE_ENUM(parser::OmpSimpleStandaloneDirective, Directive)
|
||||
NODE(parser, Only)
|
||||
NODE(parser, OpenMPAtomicConstruct)
|
||||
NODE(parser, OpenMPBlockConstruct)
|
||||
|
@ -535,8 +535,7 @@ public:
|
|||
NODE(parser, OpenMPEndLoopDirective)
|
||||
NODE(parser, OpenMPFlushConstruct)
|
||||
NODE(parser, OpenMPLoopConstruct)
|
||||
NODE(parser, OpenMPSimpleConstruct)
|
||||
NODE_ENUM(parser::OpenMPSimpleConstruct, Directive)
|
||||
NODE(parser, OpenMPSimpleStandaloneConstruct)
|
||||
NODE(parser, OpenMPStandaloneConstruct)
|
||||
NODE(parser, OpenMPSectionsConstruct)
|
||||
NODE(parser, OpenMPSingleConstruct)
|
||||
|
|
|
@ -297,25 +297,42 @@ TYPE_PARSER(sourced(construct<OmpCancelType>(
|
|||
"TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)))))
|
||||
|
||||
// Cancellation Point construct
|
||||
TYPE_PARSER(construct<OpenMPCancellationPointConstruct>(
|
||||
sourced("CANCELLATION POINT" >> Parser<OmpCancelType>{})))
|
||||
TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
|
||||
verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{})))
|
||||
|
||||
// Cancel construct
|
||||
TYPE_PARSER(construct<OpenMPCancelConstruct>(
|
||||
sourced("CANCEL" >> Parser<OmpCancelType>{}),
|
||||
maybe("IF" >> parenthesized(scalarLogicalExpr))))
|
||||
TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
|
||||
Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr)))))
|
||||
|
||||
// Flush construct
|
||||
TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(
|
||||
"FLUSH" >> maybe(parenthesized(Parser<OmpObjectList>{})))))
|
||||
verbatim("FLUSH"_tok), maybe(parenthesized(Parser<OmpObjectList>{})))))
|
||||
|
||||
// Standalone directives
|
||||
TYPE_PARSER(sourced(construct<OmpStandaloneDirective>(first(
|
||||
// Simple Standalone Directives
|
||||
TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
|
||||
"BARRIER" >> pure(OmpSimpleStandaloneDirective::Directive::Barrier),
|
||||
"ORDERED" >> pure(OmpSimpleStandaloneDirective::Directive::Ordered),
|
||||
"TARGET ENTER DATA" >>
|
||||
pure(OmpStandaloneDirective::Directive::TargetEnterData),
|
||||
pure(OmpSimpleStandaloneDirective::Directive::TargetEnterData),
|
||||
"TARGET EXIT DATA" >>
|
||||
pure(OmpStandaloneDirective::Directive::TargetExitData),
|
||||
"TARGET UPDATE" >> pure(OmpStandaloneDirective::Directive::TargetUpdate)))))
|
||||
pure(OmpSimpleStandaloneDirective::Directive::TargetExitData),
|
||||
"TARGET UPDATE" >>
|
||||
pure(OmpSimpleStandaloneDirective::Directive::TargetUpdate),
|
||||
"TASKWAIT" >> pure(OmpSimpleStandaloneDirective::Directive::Taskwait),
|
||||
"TASKYIELD" >> pure(OmpSimpleStandaloneDirective::Directive::Taskyield)))))
|
||||
|
||||
TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
|
||||
Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
|
||||
|
||||
// Standalone Constructs
|
||||
TYPE_PARSER(
|
||||
sourced(construct<OpenMPStandaloneConstruct>(
|
||||
Parser<OpenMPSimpleStandaloneConstruct>{}) ||
|
||||
construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
|
||||
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
|
||||
construct<OpenMPStandaloneConstruct>(
|
||||
Parser<OpenMPCancellationPointConstruct>{})) /
|
||||
endOfLine)
|
||||
|
||||
// Directives enclosing structured-block
|
||||
TYPE_PARSER(sourced(construct<OmpBlockDirective>(
|
||||
|
@ -454,17 +471,6 @@ TYPE_PARSER(construct<OpenMPBlockConstruct>(Parser<OmpBlockDirective>{},
|
|||
Parser<OmpClauseList>{} / endOmpLine, block,
|
||||
Parser<OmpEndBlockDirective>{}))
|
||||
|
||||
// Simple constructs without clauses
|
||||
TYPE_PARSER(
|
||||
sourced(construct<OpenMPSimpleConstruct>(first(
|
||||
"BARRIER" >> pure(OpenMPSimpleConstruct::Directive::Barrier),
|
||||
"TASKWAIT" >> pure(OpenMPSimpleConstruct::Directive::Taskwait),
|
||||
"TASKYIELD" >> pure(OpenMPSimpleConstruct::Directive::Taskyield)))) /
|
||||
endOmpLine)
|
||||
|
||||
TYPE_PARSER(construct<OpenMPStandaloneConstruct>(
|
||||
Parser<OmpStandaloneDirective>{}, Parser<OmpClauseList>{} / endOmpLine))
|
||||
|
||||
// OMP SINGLE
|
||||
TYPE_PARSER(startOmpLine >> construct<OmpEndSingle>(verbatim("END SINGLE"_tok),
|
||||
Parser<OmpClauseList>{}) /
|
||||
|
@ -507,21 +513,18 @@ TYPE_PARSER(construct<OmpSection>(verbatim("SECTION"_tok) / endOmpLine))
|
|||
|
||||
TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
|
||||
startOmpLine >>
|
||||
first(construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPSimpleConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPSingleConstruct>{}),
|
||||
first(construct<OpenMPConstruct>(Parser<OpenMPSingleConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
|
||||
construct<OpenMPConstruct>(
|
||||
Parser<OpenMPParallelSectionsConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPWorkshareConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}),
|
||||
// OpenMPBlockConstruct is attempted before
|
||||
// OpenMPStandaloneConstruct to resolve !$OMP ORDERED
|
||||
construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPCancelConstruct>{}),
|
||||
construct<OpenMPConstruct>(
|
||||
Parser<OpenMPCancellationPointConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OpenMPFlushConstruct>{}),
|
||||
construct<OpenMPConstruct>(Parser<OmpSection>{})))
|
||||
|
||||
// END OMP Block directives
|
||||
|
|
|
@ -3666,38 +3666,47 @@ struct OmpCancelType {
|
|||
};
|
||||
|
||||
// CANCELLATION POINT
|
||||
WRAPPER_CLASS(OpenMPCancellationPointConstruct, OmpCancelType);
|
||||
struct OpenMPCancellationPointConstruct {
|
||||
TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct);
|
||||
CharBlock source;
|
||||
std::tuple<Verbatim, OmpCancelType> t;
|
||||
};
|
||||
|
||||
// CANCEL
|
||||
struct OpenMPCancelConstruct {
|
||||
TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
|
||||
WRAPPER_CLASS(If, ScalarLogicalExpr);
|
||||
std::tuple<OmpCancelType, std::optional<If>> t;
|
||||
CharBlock source;
|
||||
std::tuple<Verbatim, OmpCancelType, std::optional<If>> t;
|
||||
};
|
||||
|
||||
// FLUSH
|
||||
struct OpenMPFlushConstruct {
|
||||
WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, std::optional<OmpObjectList>);
|
||||
TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
|
||||
CharBlock source;
|
||||
std::tuple<Verbatim, std::optional<OmpObjectList>> t;
|
||||
};
|
||||
|
||||
// These simple constructs do not have clauses.
|
||||
struct OpenMPSimpleConstruct {
|
||||
ENUM_CLASS(Directive, Barrier, Taskwait, Taskyield)
|
||||
WRAPPER_CLASS_BOILERPLATE(OpenMPSimpleConstruct, Directive);
|
||||
struct OmpSimpleStandaloneDirective {
|
||||
ENUM_CLASS(Directive, Barrier, Taskwait, Taskyield, TargetEnterData,
|
||||
TargetExitData, TargetUpdate, Ordered)
|
||||
WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, Directive);
|
||||
CharBlock source;
|
||||
};
|
||||
|
||||
// Standalone constructs; these can have clauses.
|
||||
struct OmpStandaloneDirective {
|
||||
ENUM_CLASS(Directive, TargetEnterData, TargetExitData, TargetUpdate)
|
||||
WRAPPER_CLASS_BOILERPLATE(OmpStandaloneDirective, Directive);
|
||||
struct OpenMPSimpleStandaloneConstruct {
|
||||
TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
|
||||
CharBlock source;
|
||||
std::tuple<OmpSimpleStandaloneDirective, OmpClauseList> t;
|
||||
};
|
||||
|
||||
struct OpenMPStandaloneConstruct {
|
||||
TUPLE_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
|
||||
std::tuple<OmpStandaloneDirective, OmpClauseList> t;
|
||||
UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
|
||||
CharBlock source;
|
||||
std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
|
||||
OpenMPCancelConstruct, OpenMPCancellationPointConstruct>
|
||||
u;
|
||||
};
|
||||
|
||||
WRAPPER_CLASS(OmpEndBlockDirective, OmpBlockDirective);
|
||||
|
@ -3722,13 +3731,10 @@ struct OpenMPLoopConstruct {
|
|||
|
||||
struct OpenMPConstruct {
|
||||
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
|
||||
std::variant<OpenMPStandaloneConstruct, OpenMPSimpleConstruct,
|
||||
OpenMPSingleConstruct, OpenMPSectionsConstruct,
|
||||
OpenMPParallelSectionsConstruct, OpenMPWorkshareConstruct,
|
||||
OpenMPLoopConstruct, OpenMPBlockConstruct,
|
||||
OpenMPCancellationPointConstruct, OpenMPCancelConstruct,
|
||||
OpenMPFlushConstruct, OpenMPAtomicConstruct, OpenMPCriticalConstruct,
|
||||
OmpSection>
|
||||
std::variant<OpenMPStandaloneConstruct, OpenMPSingleConstruct,
|
||||
OpenMPSectionsConstruct, OpenMPParallelSectionsConstruct,
|
||||
OpenMPWorkshareConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct,
|
||||
OpenMPAtomicConstruct, OpenMPCriticalConstruct, OmpSection>
|
||||
u;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2046,17 +2046,29 @@ public:
|
|||
}
|
||||
}
|
||||
void Unparse(const OmpObjectList &x) { Walk(x.v, ","); }
|
||||
void Unparse(const OmpStandaloneDirective &x) {
|
||||
void Unparse(const OmpSimpleStandaloneDirective &x) {
|
||||
switch (x.v) {
|
||||
case OmpStandaloneDirective::Directive::TargetEnterData:
|
||||
case OmpSimpleStandaloneDirective::Directive::Barrier:
|
||||
Word("BARRIER ");
|
||||
break;
|
||||
case OmpSimpleStandaloneDirective::Directive::Taskwait:
|
||||
Word("TASKWAIT ");
|
||||
break;
|
||||
case OmpSimpleStandaloneDirective::Directive::Taskyield:
|
||||
Word("TASKYIELD ");
|
||||
break;
|
||||
case OmpSimpleStandaloneDirective::Directive::TargetEnterData:
|
||||
Word("TARGET ENTER DATA ");
|
||||
break;
|
||||
case OmpStandaloneDirective::Directive::TargetExitData:
|
||||
case OmpSimpleStandaloneDirective::Directive::TargetExitData:
|
||||
Word("TARGET EXIT DATA ");
|
||||
break;
|
||||
case OmpStandaloneDirective::Directive::TargetUpdate:
|
||||
case OmpSimpleStandaloneDirective::Directive::TargetUpdate:
|
||||
Word("TARGET UPDATE ");
|
||||
break;
|
||||
case OmpSimpleStandaloneDirective::Directive::Ordered:
|
||||
Word("ORDERED ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void Unparse(const OmpBlockDirective &x) {
|
||||
|
@ -2305,7 +2317,7 @@ public:
|
|||
void Unparse(const OpenMPCancellationPointConstruct &x) {
|
||||
BeginOpenMP();
|
||||
Word("!$OMP CANCELLATION POINT ");
|
||||
Walk(x.v);
|
||||
Walk(std::get<OmpCancelType>(x.t));
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
}
|
||||
|
@ -2320,11 +2332,7 @@ public:
|
|||
void Unparse(const OpenMPFlushConstruct &x) {
|
||||
BeginOpenMP();
|
||||
Word("!$OMP FLUSH");
|
||||
if ((x.v).has_value()) {
|
||||
Put("(");
|
||||
Walk(x.v);
|
||||
Put(")");
|
||||
}
|
||||
Walk("(", std::get<std::optional<OmpObjectList>>(x.t), ")");
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
}
|
||||
|
@ -2338,21 +2346,10 @@ public:
|
|||
EndOpenMP();
|
||||
}
|
||||
void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); }
|
||||
void Unparse(const OpenMPSimpleConstruct &x) {
|
||||
void Unparse(const OpenMPSimpleStandaloneConstruct &x) {
|
||||
BeginOpenMP();
|
||||
Word("!$OMP ");
|
||||
switch (x.v) {
|
||||
case OpenMPSimpleConstruct::Directive::Barrier: Word("BARRIER"); break;
|
||||
case OpenMPSimpleConstruct::Directive::Taskwait: Word("TASKWAIT"); break;
|
||||
case OpenMPSimpleConstruct::Directive::Taskyield: Word("TASKYIELD"); break;
|
||||
}
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
}
|
||||
void Unparse(const OpenMPStandaloneConstruct &x) {
|
||||
BeginOpenMP();
|
||||
Word("!$OMP ");
|
||||
Walk(std::get<OmpStandaloneDirective>(x.t));
|
||||
Walk(std::get<OmpSimpleStandaloneDirective>(x.t));
|
||||
Walk(std::get<OmpClauseList>(x.t));
|
||||
Put("\n");
|
||||
EndOpenMP();
|
||||
|
|
|
@ -104,7 +104,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
|
|||
SetContextAllowed(allowed);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &x) {
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPSingleConstruct &x) {
|
|||
SetContextAllowed(allowed);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPSingleConstruct &x) {
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPSingleConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ void OmpStructureChecker::Enter(const parser::OmpEndSingle &x) {
|
|||
SetContextAllowedOnce(allowedOnce);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(const parser::OmpEndSingle &x) {
|
||||
void OmpStructureChecker::Leave(const parser::OmpEndSingle &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPWorkshareConstruct &x) {
|
|||
PushContext(dir.source, OmpDirective::WORKSHARE);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPWorkshareConstruct &x) {
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPWorkshareConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
|
@ -158,10 +158,64 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclareSimdConstruct &x) {
|
|||
PushContext(dir.source, OmpDirective::DECLARE_SIMD);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &x) {
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(
|
||||
const parser::OpenMPSimpleStandaloneConstruct &x) {
|
||||
const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
|
||||
PushContext(dir.source);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(
|
||||
const parser::OpenMPSimpleStandaloneConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OpenMPFlushConstruct &x) {
|
||||
const auto &dir{std::get<parser::Verbatim>(x.t)};
|
||||
PushContext(dir.source, OmpDirective::FLUSH);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) {
|
||||
const auto &dir{std::get<parser::Verbatim>(x.t)};
|
||||
PushContext(dir.source, OmpDirective::CANCEL);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(
|
||||
const parser::OpenMPCancellationPointConstruct &x) {
|
||||
const auto &dir{std::get<parser::Verbatim>(x.t)};
|
||||
PushContext(dir.source, OmpDirective::CANCELLATION_POINT);
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Leave(
|
||||
const parser::OpenMPCancellationPointConstruct &) {
|
||||
ompContext_.pop_back();
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OmpSimpleStandaloneDirective &x) {
|
||||
switch (x.v) {
|
||||
case parser::OmpSimpleStandaloneDirective::Directive::Ordered: {
|
||||
// 2.13.8 ordered-construct-clause -> depend-clause
|
||||
SetContextDirectiveEnum(OmpDirective::ORDERED);
|
||||
OmpClauseSet allowed{OmpClause::DEPEND};
|
||||
SetContextAllowed(allowed);
|
||||
}
|
||||
default:
|
||||
// TODO others
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OmpBlockDirective &x) {
|
||||
switch (x.v) {
|
||||
// 2.5 parallel-clause -> if-clause |
|
||||
|
|
|
@ -79,6 +79,16 @@ public:
|
|||
void Enter(const parser::OpenMPDeclareSimdConstruct &);
|
||||
void Leave(const parser::OpenMPDeclareSimdConstruct &);
|
||||
|
||||
void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
|
||||
void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
|
||||
void Enter(const parser::OmpSimpleStandaloneDirective &);
|
||||
void Enter(const parser::OpenMPFlushConstruct &);
|
||||
void Leave(const parser::OpenMPFlushConstruct &);
|
||||
void Enter(const parser::OpenMPCancelConstruct &);
|
||||
void Leave(const parser::OpenMPCancelConstruct &);
|
||||
void Enter(const parser::OpenMPCancellationPointConstruct &);
|
||||
void Leave(const parser::OpenMPCancellationPointConstruct &);
|
||||
|
||||
void Leave(const parser::OmpClauseList &);
|
||||
void Enter(const parser::OmpClause &);
|
||||
void Enter(const parser::OmpNowait &);
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
integer :: b = 128
|
||||
integer :: c = 32
|
||||
integer, parameter :: num = 16
|
||||
real(8) :: arrayA(256), arrayB(512)
|
||||
|
||||
arrayA = 1.414
|
||||
arrayB = 3.14
|
||||
N = 1024
|
||||
|
||||
! 2.5 parallel-clause -> if-clause |
|
||||
|
@ -276,4 +280,19 @@
|
|||
a = 3.14
|
||||
enddo
|
||||
enddo
|
||||
end
|
||||
|
||||
! Standalone Directives (basic)
|
||||
|
||||
!$omp taskyield
|
||||
!$omp barrier
|
||||
!$omp taskwait
|
||||
! !$omp target enter data map(to:arrayA) map(alloc:arrayB)
|
||||
! !$omp target update from(arrayA) to(arrayB)
|
||||
! !$omp target exit data map(from:arrayA) map(delete:arrayB)
|
||||
!$omp ordered depend(source)
|
||||
!ERROR: Internal: no symbol found for 'i'
|
||||
!$omp ordered depend(sink:i-1)
|
||||
!$omp flush (c)
|
||||
!$omp cancel DO
|
||||
!$omp cancellation point parallel
|
||||
end program
|
||||
|
|
Loading…
Reference in a new issue