namespace Fortran::semantics {
-static constexpr OmpDirectiveSet parallelSet{
- OmpDirective::DISTRIBUTE_PARALLEL_DO,
- OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL,
- OmpDirective::PARALLEL_DO, OmpDirective::PARALLEL_DO_SIMD,
- OmpDirective::PARALLEL_SECTIONS, OmpDirective::PARALLEL_WORKSHARE,
- OmpDirective::TARGET_PARALLEL, OmpDirective::TARGET_PARALLEL_DO,
- OmpDirective::TARGET_PARALLEL_DO_SIMD,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
- OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO,
- OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
-static constexpr OmpDirectiveSet doSet{OmpDirective::DISTRIBUTE_PARALLEL_DO,
- OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL_DO,
- OmpDirective::PARALLEL_DO_SIMD, OmpDirective::DO, OmpDirective::DO_SIMD,
- OmpDirective::TARGET_PARALLEL_DO, OmpDirective::TARGET_PARALLEL_DO_SIMD,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
- OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO,
- OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
-static constexpr OmpDirectiveSet simdSet{
- OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::DISTRIBUTE_SIMD,
- OmpDirective::PARALLEL_DO_SIMD, OmpDirective::DO_SIMD, OmpDirective::SIMD,
- OmpDirective::TARGET_PARALLEL_DO_SIMD,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_SIMD, OmpDirective::TARGET_SIMD,
- OmpDirective::TASKLOOP_SIMD,
- OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
- OmpDirective::TEAMS_DISTRIBUTE_SIMD};
-static constexpr OmpDirectiveSet doSimdSet{
- OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL_DO_SIMD,
- OmpDirective::DO_SIMD, OmpDirective::TARGET_PARALLEL_DO_SIMD,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
- OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
-static constexpr OmpDirectiveSet taskloopSet{
- OmpDirective::TASKLOOP, OmpDirective::TASKLOOP_SIMD};
-static constexpr OmpDirectiveSet targetSet{OmpDirective::TARGET,
- OmpDirective::TARGET_PARALLEL, OmpDirective::TARGET_PARALLEL_DO,
- OmpDirective::TARGET_PARALLEL_DO_SIMD, OmpDirective::TARGET_SIMD,
- OmpDirective::TARGET_TEAMS, OmpDirective::TARGET_TEAMS_DISTRIBUTE,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
- OmpDirective::TARGET_TEAMS_DISTRIBUTE_SIMD};
-
std::string OmpStructureChecker::ContextDirectiveAsFortran() {
auto dir{EnumToString(GetContext().directive)};
std::replace(dir.begin(), dir.end(), '_', ' ');
using OmpClauseSet = common::EnumSet<OmpClause, OmpClause_enumSize>;
+static constexpr OmpDirectiveSet parallelSet{
+ OmpDirective::DISTRIBUTE_PARALLEL_DO,
+ OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL,
+ OmpDirective::PARALLEL_DO, OmpDirective::PARALLEL_DO_SIMD,
+ OmpDirective::PARALLEL_SECTIONS, OmpDirective::PARALLEL_WORKSHARE,
+ OmpDirective::TARGET_PARALLEL, OmpDirective::TARGET_PARALLEL_DO,
+ OmpDirective::TARGET_PARALLEL_DO_SIMD,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
+ OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO,
+ OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
+static constexpr OmpDirectiveSet doSet{OmpDirective::DISTRIBUTE_PARALLEL_DO,
+ OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL_DO,
+ OmpDirective::PARALLEL_DO_SIMD, OmpDirective::DO, OmpDirective::DO_SIMD,
+ OmpDirective::TARGET_PARALLEL_DO, OmpDirective::TARGET_PARALLEL_DO_SIMD,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
+ OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO,
+ OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
+static constexpr OmpDirectiveSet doSimdSet{
+ OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::PARALLEL_DO_SIMD,
+ OmpDirective::DO_SIMD, OmpDirective::TARGET_PARALLEL_DO_SIMD,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
+ OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD};
+static constexpr OmpDirectiveSet taskloopSet{
+ OmpDirective::TASKLOOP, OmpDirective::TASKLOOP_SIMD};
+static constexpr OmpDirectiveSet targetSet{OmpDirective::TARGET,
+ OmpDirective::TARGET_PARALLEL, OmpDirective::TARGET_PARALLEL_DO,
+ OmpDirective::TARGET_PARALLEL_DO_SIMD, OmpDirective::TARGET_SIMD,
+ OmpDirective::TARGET_TEAMS, OmpDirective::TARGET_TEAMS_DISTRIBUTE,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_SIMD};
+static constexpr OmpDirectiveSet simdSet{
+ OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD, OmpDirective::DISTRIBUTE_SIMD,
+ OmpDirective::PARALLEL_DO_SIMD, OmpDirective::DO_SIMD, OmpDirective::SIMD,
+ OmpDirective::TARGET_PARALLEL_DO_SIMD,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_SIMD, OmpDirective::TARGET_SIMD,
+ OmpDirective::TASKLOOP_SIMD,
+ OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD,
+ OmpDirective::TEAMS_DISTRIBUTE_SIMD};
+
class OmpStructureChecker : public virtual BaseChecker {
public:
OmpStructureChecker(SemanticsContext &context) : context_{context} {}
template<typename A> bool Pre(const A &) { return true; }
template<typename A> void Post(const A &) {}
+ bool Pre(const parser::SpecificationPart &x) {
+ Walk(std::get<std::list<parser::OpenMPDeclarativeConstruct>>(x.t));
+ return false;
+ }
+
bool Pre(const parser::OpenMPBlockConstruct &);
void Post(const parser::OpenMPBlockConstruct &) { PopContext(); }
void Post(const parser::OmpBeginBlockDirective &) {
// variables on Data-sharing attribute clauses
std::map<const Symbol *, Symbol::Flag> objectWithDSA;
bool withinConstruct{false};
+ std::size_t associatedLoopLevel{0};
};
// back() is the top of the stack
OmpContext &GetContext() {
auto it{GetContext().objectWithDSA.find(&symbol)};
return it != GetContext().objectWithDSA.end();
}
+ void SetContextAssociatedLoopLevel(std::size_t level) {
+ GetContext().associatedLoopLevel = level;
+ }
+ std::size_t GetAssociatedLoopLevelFromClauses(const parser::OmpClauseList &);
Symbol &MakeAssocSymbol(const SourceName &name, Symbol &prev) {
const auto pair{
}
bool HasDataSharingAttributeObject(const Symbol &);
+ const parser::DoConstruct *GetDoConstructIf(
+ const parser::ExecutionPartConstruct &);
+ // Predetermined DSA rules
+ void PrivatizeAssociatedLoopIndex(const parser::OpenMPLoopConstruct &);
+
void ResolveOmpObjectList(const parser::OmpObjectList &, Symbol::Flag);
void ResolveOmpObject(const parser::OmpObject &, Symbol::Flag);
Symbol *ResolveOmp(const parser::Name &, Symbol::Flag);
bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
+ const auto &clauseList{std::get<parser::OmpClauseList>(beginLoopDir.t)};
switch (beginDir.v) {
case parser::OmpLoopDirective::Directive::Distribute:
PushContext(beginDir.source, OmpDirective::DISTRIBUTE);
break;
+ case parser::OmpLoopDirective::Directive::DistributeParallelDo:
+ PushContext(beginDir.source, OmpDirective::DISTRIBUTE_PARALLEL_DO);
+ break;
+ case parser::OmpLoopDirective::Directive::DistributeParallelDoSimd:
+ PushContext(beginDir.source, OmpDirective::DISTRIBUTE_PARALLEL_DO_SIMD);
+ break;
+ case parser::OmpLoopDirective::Directive::DistributeSimd:
+ PushContext(beginDir.source, OmpDirective::DISTRIBUTE_SIMD);
+ break;
case parser::OmpLoopDirective::Directive::Do:
PushContext(beginDir.source, OmpDirective::DO);
break;
case parser::OmpLoopDirective::Directive::Simd:
PushContext(beginDir.source, OmpDirective::SIMD);
break;
+ case parser::OmpLoopDirective::Directive::TargetParallelDo:
+ PushContext(beginDir.source, OmpDirective::TARGET_PARALLEL_DO);
+ break;
+ case parser::OmpLoopDirective::Directive::TargetParallelDoSimd:
+ PushContext(beginDir.source, OmpDirective::TARGET_PARALLEL_DO_SIMD);
+ break;
+ case parser::OmpLoopDirective::Directive::TargetTeamsDistribute:
+ PushContext(beginDir.source, OmpDirective::TARGET_TEAMS_DISTRIBUTE);
+ break;
+ case parser::OmpLoopDirective::Directive::TargetTeamsDistributeParallelDo:
+ PushContext(
+ beginDir.source, OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO);
+ break;
+ case parser::OmpLoopDirective::Directive::TargetTeamsDistributeParallelDoSimd:
+ PushContext(beginDir.source,
+ OmpDirective::TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
+ break;
+ case parser::OmpLoopDirective::Directive::TargetTeamsDistributeSimd:
+ PushContext(beginDir.source, OmpDirective::TARGET_TEAMS_DISTRIBUTE_SIMD);
+ break;
+ case parser::OmpLoopDirective::Directive::TargetSimd:
+ PushContext(beginDir.source, OmpDirective::TARGET_SIMD);
+ break;
case parser::OmpLoopDirective::Directive::Taskloop:
PushContext(beginDir.source, OmpDirective::TASKLOOP);
break;
case parser::OmpLoopDirective::Directive::TaskloopSimd:
PushContext(beginDir.source, OmpDirective::TASKLOOP_SIMD);
break;
- default:
- // TODO others
+ case parser::OmpLoopDirective::Directive::TeamsDistribute:
+ PushContext(beginDir.source, OmpDirective::TEAMS_DISTRIBUTE);
+ break;
+ case parser::OmpLoopDirective::Directive::TeamsDistributeParallelDo:
+ PushContext(beginDir.source, OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO);
+ break;
+ case parser::OmpLoopDirective::Directive::TeamsDistributeParallelDoSimd:
+ PushContext(
+ beginDir.source, OmpDirective::TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
+ break;
+ case parser::OmpLoopDirective::Directive::TeamsDistributeSimd:
+ PushContext(beginDir.source, OmpDirective::TEAMS_DISTRIBUTE_SIMD);
break;
}
ClearDataSharingAttributeObjects();
+ SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
+ PrivatizeAssociatedLoopIndex(x);
return true;
}
+const parser::DoConstruct *OmpAttributeVisitor::GetDoConstructIf(
+ const parser::ExecutionPartConstruct &x) {
+ if (auto *y{std::get_if<parser::ExecutableConstruct>(&x.u)}) {
+ if (auto *z{std::get_if<Indirection<parser::DoConstruct>>(&y->u)}) {
+ return &z->value();
+ }
+ }
+ return nullptr;
+}
+
+std::size_t OmpAttributeVisitor::GetAssociatedLoopLevelFromClauses(
+ const parser::OmpClauseList &x) {
+ std::size_t orderedLevel{0};
+ std::size_t collapseLevel{0};
+ for (const auto &clause : x.v) {
+ if (const auto *orderedClause{
+ std::get_if<parser::OmpClause::Ordered>(&clause.u)}) {
+ if (const auto v{
+ evaluate::ToInt64(resolver_.EvaluateIntExpr(orderedClause->v))}) {
+ orderedLevel = *v;
+ }
+ }
+ if (const auto *collapseClause{
+ std::get_if<parser::OmpClause::Collapse>(&clause.u)}) {
+ if (const auto v{evaluate::ToInt64(
+ resolver_.EvaluateIntExpr(collapseClause->v))}) {
+ collapseLevel = *v;
+ }
+ }
+ }
+
+ if (orderedLevel && (!collapseLevel || orderedLevel >= collapseLevel)) {
+ return orderedLevel;
+ } else if (!orderedLevel && collapseLevel) {
+ return collapseLevel;
+ } // orderedLevel < collapseLevel is an error handled in structural checks
+ return 1; // default is outermost loop
+}
+
+// 2.15.1.1 Data-sharing Attribute Rules - Predetermined
+// - The loop iteration variable(s) in the associated do-loop(s) of a do,
+// parallel do, taskloop, or distribute construct is (are) private.
+// - The loop iteration variable in the associated do-loop of a simd construct
+// with just one associated do-loop is linear with a linear-step that is the
+// increment of the associated do-loop.
+// - The loop iteration variables in the associated do-loops of a simd
+// construct with multiple associated do-loops are lastprivate.
+//
+// TODO: This assumes that the do-loops association for collapse/ordered
+// clause has been performed (the number of nested do-loops >= n).
+void OmpAttributeVisitor::PrivatizeAssociatedLoopIndex(
+ const parser::OpenMPLoopConstruct &x) {
+ std::size_t level{GetContext().associatedLoopLevel};
+ Symbol::Flag ivDSA{Symbol::Flag::OmpPrivate};
+ if (simdSet.test(GetContext().directive)) {
+ if (level == 1) {
+ ivDSA = Symbol::Flag::OmpLinear;
+ } else {
+ ivDSA = Symbol::Flag::OmpLastPrivate;
+ }
+ }
+
+ auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
+ for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) {
+ // go through all the nested do-loops and resolve index variables
+ auto &loopControl{loop->GetLoopControl().value()};
+ using Bounds = parser::LoopControl::Bounds;
+ const Bounds &bounds{std::get<Bounds>(loopControl.u)};
+ const parser::Name &iv{bounds.name.thing};
+ if (auto *symbol{ResolveOmp(iv, ivDSA)}) {
+ iv.symbol = symbol; // adjust the symbol within region
+ AddToContextObjectWithDSA(*symbol, ivDSA);
+ }
+
+ const auto &block{std::get<parser::Block>(loop->t)};
+ const auto it{block.begin()};
+ loop = it != block.end() ? GetDoConstructIf(*it) : nullptr;
+ }
+ CHECK(level == 0);
+}
+
bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) {
const auto &beginSectionsDir{
std::get<parser::OmpBeginSectionsDirective>(x.t)};
omp-symbol05.f90
omp-symbol06.f90
omp-symbol07.f90
+ omp-symbol08.f90
kinds01.f90
kinds03.f90
procinterface01.f90
!ERROR: COLLAPSE clause is not allowed on the PARALLEL directive
!$omp parallel collapse(2)
do i = 1, N
- a = 3.14
+ do j = 1, N
+ a = 3.14
+ enddo
enddo
!$omp end parallel
enddo
!ERROR: The parameter of the ORDERED clause must be greater than or equal to the parameter of the COLLAPSE clause
- !$omp do collapse(num) ordered(1+2+3+4)
+ !$omp do collapse(num-14) ordered(1)
do i = 1, N
do j = 1, N
do k = 1, N
!ERROR: NOGROUP clause is not allowed on the DO SIMD directive
!$omp do simd ordered(2) NOGROUP
do i = 1, N
- a = 3.14
+ do j = 1, N
+ a = 3.14
+ enddo
enddo
!$omp end parallel
!ERROR: At most one COLLAPSE clause can appear on the DISTRIBUTE directive
!$omp distribute collapse(2) collapse(3)
do i = 1, N
- a = 3.14
+ do j = 1, N
+ do k = 1, N
+ a = 3.14
+ enddo
+ enddo
enddo
!$omp end distribute
!$omp end target
!DEF: /mm/c (Implicit) ObjectEntity REAL(4)
c = 2.0
!$omp parallel do private(a,t,/c/) shared(c)
- !DEF: /mm/i (Implicit) ObjectEntity INTEGER(4)
+ !DEF: /mm/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
do i=1,10
!DEF: /mm/Block1/a (OmpPrivate) HostAssoc REAL(4)
!REF: /mm/b
- !REF: /mm/i
+ !REF: /mm/Block1/i
a = a+b(i)
!DEF: /mm/Block1/t (OmpPrivate) HostAssoc TYPE(myty)
!REF: /md/myty/a
- !REF: /mm/i
+ !REF: /mm/Block1/i
t%a = i
!DEF: /mm/Block1/y (OmpPrivate) HostAssoc REAL(4)
y = 0.
!DEF: /mm/Block1/x (OmpPrivate) HostAssoc REAL(4)
!REF: /mm/Block1/a
- !REF: /mm/i
+ !REF: /mm/Block1/i
!REF: /mm/Block1/y
x = a+i+y
!REF: /mm/c
!DEF: /MainProgram1/Block1/a (OmpPrivate) HostAssoc REAL(8)
a = 2.
!$omp do private(a)
- !DEF: /MainProgram1/i (Implicit) ObjectEntity INTEGER(4)
+ !DEF: /MainProgram1/Block1/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
do i=1,10
!DEF: /MainProgram1/Block1/Block1/a (OmpPrivate) HostAssoc REAL(8)
a = 1.
!DEF: /MainProgram1/a (Implicit) ObjectEntity REAL(4)
a = 1.
!$omp parallel do firstprivate(a) lastprivate(a)
- !DEF: /MainProgram1/i (Implicit) ObjectEntity INTEGER(4)
+ !DEF: /MainProgram1/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
do i=1,10
!DEF: /MainProgram1/Block1/a (OmpFirstPrivate, OmpLastPrivate) HostAssoc REAL(4)
a = 2.
--- /dev/null
+!OPTIONS: -fopenmp
+
+! 2.15.1.1 Predetermined rules for associated do-loops index variable
+! a) The loop iteration variable(s) in the associated do-loop(s) of a do,
+! parallel do, taskloop, or distribute construct is (are) private.
+! b) The loop iteration variable in the associated do-loop of a simd construct
+! with just one associated do-loop is linear with a linear-step that is the
+! increment of the associated do-loop.
+! c) The loop iteration variables in the associated do-loops of a simd
+! construct with multiple associated do-loops are lastprivate.
+! - TBD
+
+! All the tests assume that the do-loops association for collapse/ordered
+! clause has been performed (the number of nested do-loops >= n).
+
+! Rule a)
+! TODO: nested constructs (k should be private too)
+!DEF: /test_do (Subroutine) Subprogram
+subroutine test_do
+ implicit none
+ !DEF: /test_do/a ObjectEntity REAL(4)
+ real a(20,20,20)
+ !DEF: /test_do/i ObjectEntity INTEGER(4)
+ !DEF: /test_do/j ObjectEntity INTEGER(4)
+ !DEF: /test_do/k ObjectEntity INTEGER(4)
+ integer i, j, k
+!$omp parallel
+ !REF: /test_do/i
+ i = 99
+!$omp do collapse(2)
+ !DEF: /test_do/Block1/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
+ do i=1,5
+ !DEF: /test_do/Block1/Block1/j (OmpPrivate) HostAssoc INTEGER(4)
+ do j=6,10
+ !REF: /test_do/a
+ a(1,1,1) = 0.
+ !REF: /test_do/k
+ do k=11,15
+ !REF: /test_do/a
+ !REF: /test_do/k
+ !REF: /test_do/Block1/Block1/j
+ !REF: /test_do/Block1/Block1/i
+ a(k,j,i) = 1.
+ end do
+ end do
+ end do
+!$omp end parallel
+end subroutine test_do
+
+! Rule a)
+!DEF: /test_pardo (Subroutine) Subprogram
+subroutine test_pardo
+ implicit none
+ !DEF: /test_pardo/a ObjectEntity REAL(4)
+ real a(20,20,20)
+ !DEF: /test_pardo/i ObjectEntity INTEGER(4)
+ !DEF: /test_pardo/j ObjectEntity INTEGER(4)
+ !DEF: /test_pardo/k ObjectEntity INTEGER(4)
+ integer i, j, k
+!$omp parallel do collapse(2) private(k) ordered(2)
+ !DEF: /test_pardo/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
+ do i=1,5
+ !DEF: /test_pardo/Block1/j (OmpPrivate) HostAssoc INTEGER(4)
+ do j=6,10
+ !REF: /test_pardo/a
+ a(1,1,1) = 0.
+ !DEF: /test_pardo/Block1/k (OmpPrivate) HostAssoc INTEGER(4)
+ do k=11,15
+ !REF: /test_pardo/a
+ !REF: /test_pardo/Block1/k
+ !REF: /test_pardo/Block1/j
+ !REF: /test_pardo/Block1/i
+ a(k,j,i) = 1.
+ end do
+ end do
+ end do
+end subroutine test_pardo
+
+! Rule a)
+!DEF: /test_taskloop (Subroutine) Subprogram
+subroutine test_taskloop
+ implicit none
+ !DEF: /test_taskloop/a ObjectEntity REAL(4)
+ real a(5,5)
+ !DEF: /test_taskloop/i ObjectEntity INTEGER(4)
+ !DEF: /test_taskloop/j ObjectEntity INTEGER(4)
+ integer i, j
+!$omp taskloop private(j)
+ !DEF: /test_taskloop/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
+ do i=1,5
+ !DEF: /test_taskloop/Block1/j (OmpPrivate) HostAssoc INTEGER(4)
+ !REF: /test_taskloop/Block1/i
+ do j=1,i
+ !REF: /test_taskloop/a
+ !REF: /test_taskloop/Block1/j
+ !REF: /test_taskloop/Block1/i
+ a(j,i) = 3.14
+ end do
+ end do
+!$omp end taskloop
+end subroutine test_taskloop
+
+! Rule a); OpenMP 4.5 Examples teams.2.f90
+! TODO: reduction; data-mapping attributes
+!DEF: /dotprod (Subroutine) Subprogram
+!DEF: /dotprod/b ObjectEntity REAL(4)
+!DEF: /dotprod/c ObjectEntity REAL(4)
+!DEF: /dotprod/n ObjectEntity INTEGER(4)
+!DEF: /dotprod/block_size ObjectEntity INTEGER(4)
+!DEF: /dotprod/num_teams ObjectEntity INTEGER(4)
+!DEF: /dotprod/block_threads ObjectEntity INTEGER(4)
+subroutine dotprod (b, c, n, block_size, num_teams, block_threads)
+ implicit none
+ !REF: /dotprod/n
+ integer n
+ !REF: /dotprod/b
+ !REF: /dotprod/n
+ !REF: /dotprod/c
+ !DEF: /dotprod/sum ObjectEntity REAL(4)
+ real b(n), c(n), sum
+ !REF: /dotprod/block_size
+ !REF: /dotprod/num_teams
+ !REF: /dotprod/block_threads
+ !DEF: /dotprod/i ObjectEntity INTEGER(4)
+ !DEF: /dotprod/i0 ObjectEntity INTEGER(4)
+ integer block_size, num_teams, block_threads, i, i0
+ !REF: /dotprod/sum
+ sum = 0.0e0
+!$omp target map(to:b,c) map(tofrom:sum)
+!$omp teams num_teams(num_teams) thread_limit(block_threads) reduction(+:sum)
+!$omp distribute
+ !DEF: /dotprod/Block1/Block1/Block1/i0 (OmpPrivate) HostAssoc INTEGER(4)
+ !REF: /dotprod/n
+ !REF: /dotprod/block_size
+ do i0=1,n,block_size
+!$omp parallel do reduction(+:sum)
+ !DEF: /dotprod/Block1/Block1/Block1/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
+ !REF: /dotprod/i0
+ !DEF: /dotprod/min INTRINSIC (Function) ProcEntity
+ !REF: /dotprod/block_size
+ !REF: /dotprod/n
+ do i=i0,min(i0+block_size, n)
+ !REF: /dotprod/sum
+ !REF: /dotprod/b
+ !REF: /dotprod/Block1/Block1/Block1/Block1/i
+ !REF: /dotprod/c
+ sum = sum+b(i)*c(i)
+ end do
+ end do
+!$omp end teams
+!$omp end target
+ !REF: /dotprod/sum
+ print *, sum
+end subroutine dotprod
+
+! Rule b)
+! TODO: nested constructs (j, k should be private too)
+!DEF: /test_simd (Subroutine) Subprogram
+subroutine test_simd
+ implicit none
+ !DEF: /test_simd/a ObjectEntity REAL(4)
+ real a(20,20,20)
+ !DEF: /test_simd/i ObjectEntity INTEGER(4)
+ !DEF: /test_simd/j ObjectEntity INTEGER(4)
+ !DEF: /test_simd/k ObjectEntity INTEGER(4)
+ integer i, j, k
+!$omp parallel do simd
+ !DEF: /test_simd/Block1/i (OmpLinear) HostAssoc INTEGER(4)
+ do i=1,5
+ !REF: /test_simd/j
+ do j=6,10
+ !REF: /test_simd/k
+ do k=11,15
+ !REF: /test_simd/a
+ !REF: /test_simd/k
+ !REF: /test_simd/j
+ !REF: /test_simd/Block1/i
+ a(k,j,i) = 3.14
+ end do
+ end do
+ end do
+end subroutine test_simd
+
+! Rule c)
+!DEF: /test_simd_multi (Subroutine) Subprogram
+subroutine test_simd_multi
+ implicit none
+ !DEF: /test_simd_multi/a ObjectEntity REAL(4)
+ real a(20,20,20)
+ !DEF: /test_simd_multi/i ObjectEntity INTEGER(4)
+ !DEF: /test_simd_multi/j ObjectEntity INTEGER(4)
+ !DEF: /test_simd_multi/k ObjectEntity INTEGER(4)
+ integer i, j, k
+!$omp parallel do simd collapse(3)
+ !DEF: /test_simd_multi/Block1/i (OmpLastPrivate) HostAssoc INTEGER(4)
+ do i=1,5
+ !DEF: /test_simd_multi/Block1/j (OmpLastPrivate) HostAssoc INTEGER(4)
+ do j=6,10
+ !DEF: /test_simd_multi/Block1/k (OmpLastPrivate) HostAssoc INTEGER(4)
+ do k=11,15
+ !REF: /test_simd_multi/a
+ !REF: /test_simd_multi/Block1/k
+ !REF: /test_simd_multi/Block1/j
+ !REF: /test_simd_multi/Block1/i
+ a(k,j,i) = 3.14
+ end do
+ end do
+ end do
+end subroutine test_simd_multi