[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:
parent
bff1d7c39e
commit
f90404e59c
|
@ -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(), '_', ' ');
|
||||
|
|
|
@ -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} {}
|
||||
|
|
|
@ -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)};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
209
flang/test/semantics/omp-symbol08.f90
Normal file
209
flang/test/semantics/omp-symbol08.f90
Normal 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
|
Loading…
Reference in a new issue