[flang] [OpenMP] Predetermined rules for loop index variables (flang-compiler/f18#962)

This refers to three rules in OpenMP 4.5 Spec 2.15.1.1:
  * 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.

A simple example:
```
implicit none
  integer :: N = 1024
  integer i, j, k
  !$omp parallel do collapse(3)
  do i=1, N  <- i is private
     do j=1, N  <- j is private
        do k=1, N  <- k is private
        enddo
     enddo
  enddo
end
```

If `collapse` clause is not present, the associated do-loop for construct
`parallel do` is only `i` loop. With `collapse(n)`, `i`, `j`, and `k` are
all associated do-loops and the loop index variables are private to the
OpenMP construct:

```
implicit none
 !DEF: /MainProgram1/n ObjectEntity INTEGER(4)
 integer :: n = 1024
 !DEF: /MainProgram1/i ObjectEntity INTEGER(4)
 !DEF: /MainProgram1/j ObjectEntity INTEGER(4)
 !DEF: /MainProgram1/k ObjectEntity INTEGER(4)
 integer i, j, k
!$omp parallel do  collapse(3)
 !DEF: /MainProgram1/Block1/i (OmpPrivate) HostAssoc INTEGER(4)
 !REF: /MainProgram1/n
 do i=1,n
  !DEF: /MainProgram1/Block1/j (OmpPrivate) HostAssoc INTEGER(4)
  !REF: /MainProgram1/n
  do j=1,n
   !DEF: /MainProgram1/Block1/k (OmpPrivate) HostAssoc INTEGER(4)
   !REF: /MainProgram1/n
   do k=1,n
   end do
  end do
 end do
end program
```

This implementation assumes that the structural checks for do-loops
are done at this point, for example the `n` in `collapse(n)` should
be no more than the number of actual perfectly nested do-loops, etc..

Original-commit: flang-compiler/f18@572a57d3d0
Reviewed-on: https://github.com/flang-compiler/f18/pull/962
This commit is contained in:
Jinxin (Brian) Yang 2020-02-05 10:13:43 -08:00 committed by GitHub
parent bff1d7c39e
commit f90404e59c
10 changed files with 414 additions and 55 deletions

View file

@ -13,49 +13,6 @@
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(), '_', ' ');

View file

@ -46,6 +46,49 @@ ENUM_CLASS(OmpClause, ALIGNED, COLLAPSE, COPYIN, COPYPRIVATE, DEFAULT,
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} {}

View file

@ -1148,6 +1148,11 @@ public:
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 &) {
@ -1199,6 +1204,7 @@ private:
// 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() {
@ -1226,6 +1232,10 @@ private:
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{
@ -1260,6 +1270,11 @@ private:
}
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);
@ -5935,10 +5950,20 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPBlockConstruct &x) {
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;
@ -5954,20 +5979,136 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
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)};

View file

@ -229,6 +229,7 @@ set(SYMBOL_TESTS
omp-symbol05.f90
omp-symbol06.f90
omp-symbol07.f90
omp-symbol08.f90
kinds01.f90
kinds03.f90
procinterface01.f90

View file

@ -43,7 +43,9 @@
!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
@ -143,7 +145,7 @@
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
@ -309,7 +311,9 @@
!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

View file

@ -149,7 +149,11 @@ program main
!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

View file

@ -45,21 +45,21 @@ program mm
!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

View file

@ -12,7 +12,7 @@
!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.

View file

@ -8,7 +8,7 @@
!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.

View file

@ -0,0 +1,209 @@
!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