Skip to content

Commit 977cb5d

Browse files
[Flang][OpenMP] Restrict certain loops not allowed in associated loops (llvm#91818)
Extends the OmpCycleAndExitChecker to check that associated loops of a loop construct are not DO WHILE or DO without control. OpenMP 5.0 standard clearly mentions this restriction. Later standards enforce this through the definition of associated loops and canonical loop forms. https://www.openmp.org/spec-html/5.0/openmpsu41.html Fixes llvm#81949
1 parent 60ec686 commit 977cb5d

File tree

5 files changed

+26
-27
lines changed

5 files changed

+26
-27
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -84,21 +84,34 @@ class OmpWorkshareBlockChecker {
8484
parser::CharBlock source_;
8585
};
8686

87-
class OmpCycleAndExitChecker {
87+
class AssociatedLoopChecker {
8888
public:
89-
OmpCycleAndExitChecker(SemanticsContext &context, std::int64_t level)
89+
AssociatedLoopChecker(SemanticsContext &context, std::int64_t level)
9090
: context_{context}, level_{level} {}
9191

9292
template <typename T> bool Pre(const T &) { return true; }
9393
template <typename T> void Post(const T &) {}
9494

9595
bool Pre(const parser::DoConstruct &dc) {
9696
level_--;
97-
const auto &constructName{std::get<0>(std::get<0>(dc.t).statement.t)};
97+
const auto &doStmt{
98+
std::get<parser::Statement<parser::NonLabelDoStmt>>(dc.t)};
99+
const auto &constructName{
100+
std::get<std::optional<parser::Name>>(doStmt.statement.t)};
98101
if (constructName) {
99102
constructNamesAndLevels_.emplace(
100103
constructName.value().ToString(), level_);
101104
}
105+
if (level_ >= 0) {
106+
if (dc.IsDoWhile()) {
107+
context_.Say(doStmt.source,
108+
"The associated loop of a loop-associated directive cannot be a DO WHILE."_err_en_US);
109+
}
110+
if (!dc.GetLoopControl()) {
111+
context_.Say(doStmt.source,
112+
"The associated loop of a loop-associated directive cannot be a DO without control."_err_en_US);
113+
}
114+
}
102115
return true;
103116
}
104117

@@ -450,9 +463,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
450463
const auto &doBlock{std::get<parser::Block>(doConstruct->t)};
451464
CheckNoBranching(doBlock, beginDir.v, beginDir.source);
452465
}
453-
CheckDoWhile(x);
454466
CheckLoopItrVariableIsInt(x);
455-
CheckCycleConstraints(x);
467+
CheckAssociatedLoopConstraints(x);
456468
HasInvalidDistributeNesting(x);
457469
if (CurrentDirectiveIsNested() &&
458470
llvm::omp::topTeamsSet.test(GetContextParent().directive)) {
@@ -478,21 +490,6 @@ void OmpStructureChecker::SetLoopInfo(const parser::OpenMPLoopConstruct &x) {
478490
}
479491
}
480492
}
481-
void OmpStructureChecker::CheckDoWhile(const parser::OpenMPLoopConstruct &x) {
482-
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
483-
const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
484-
if (beginDir.v == llvm::omp::Directive::OMPD_do) {
485-
if (const auto &doConstruct{
486-
std::get<std::optional<parser::DoConstruct>>(x.t)}) {
487-
if (doConstruct.value().IsDoWhile()) {
488-
const auto &doStmt{std::get<parser::Statement<parser::NonLabelDoStmt>>(
489-
doConstruct.value().t)};
490-
context_.Say(doStmt.source,
491-
"The DO loop cannot be a DO WHILE with DO directive."_err_en_US);
492-
}
493-
}
494-
}
495-
}
496493

497494
void OmpStructureChecker::CheckLoopItrVariableIsInt(
498495
const parser::OpenMPLoopConstruct &x) {
@@ -647,8 +644,8 @@ std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
647644
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
648645
const auto &clauseList{std::get<parser::OmpClauseList>(beginLoopDir.t)};
649646
std::int64_t orderedCollapseLevel{1};
650-
std::int64_t orderedLevel{0};
651-
std::int64_t collapseLevel{0};
647+
std::int64_t orderedLevel{1};
648+
std::int64_t collapseLevel{1};
652649

653650
for (const auto &clause : clauseList.v) {
654651
if (const auto *collapseClause{
@@ -672,10 +669,10 @@ std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
672669
return orderedCollapseLevel;
673670
}
674671

675-
void OmpStructureChecker::CheckCycleConstraints(
672+
void OmpStructureChecker::CheckAssociatedLoopConstraints(
676673
const parser::OpenMPLoopConstruct &x) {
677674
std::int64_t ordCollapseLevel{GetOrdCollapseLevel(x)};
678-
OmpCycleAndExitChecker checker{context_, ordCollapseLevel};
675+
AssociatedLoopChecker checker{context_, ordCollapseLevel};
679676
parser::Walk(x, checker);
680677
}
681678

flang/lib/Semantics/check-omp-structure.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ class OmpStructureChecker
186186

187187
void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
188188
void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
189-
void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
189+
void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
190190
template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
191191
void CheckAtomicMemoryOrderClause(
192192
const parser::OmpAtomicClauseList *, const parser::OmpAtomicClauseList *);

flang/test/Semantics/OpenMP/clause-validity01.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@
173173
outer: do i=0, 10
174174
inner: do j=1, 10
175175
exit
176+
!ERROR: EXIT statement terminates associated loop of an OpenMP DO construct
176177
exit outer
177178
!ERROR: EXIT to construct 'outofparallel' outside of PARALLEL construct is not allowed
178179
!ERROR: EXIT to construct 'outofparallel' outside of DO construct is not allowed

flang/test/Semantics/OpenMP/do-collapse.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ program omp_doCollapse
2626
!$omp parallel do collapse(2)
2727
do i = 1, 3
2828
!ERROR: Loop control is not present in the DO LOOP
29+
!ERROR: The associated loop of a loop-associated directive cannot be a DO without control.
2930
do
3031
end do
3132
end do

flang/test/Semantics/OpenMP/do09.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
program omp_do
77
integer :: i = 0,k
88
!$omp do
9-
!ERROR: The DO loop cannot be a DO WHILE with DO directive.
9+
!ERROR: The associated loop of a loop-associated directive cannot be a DO WHILE.
1010
do while (i <= 10)
1111
print *, "it",i
1212
i = i+1
1313
end do
1414
!$omp end do
1515

1616
!$omp do
17-
!ERROR: The DO loop cannot be a DO WHILE with DO directive.
17+
!ERROR: The associated loop of a loop-associated directive cannot be a DO WHILE.
1818
do while (i <= 10)
1919
do while (j <= 10)
2020
print *, "it",k

0 commit comments

Comments
 (0)