Skip to content

[Flang][OpenMP] Restrict certain loops not allowed in associated loops #91818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 21 additions & 24 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,34 @@ class OmpWorkshareBlockChecker {
parser::CharBlock source_;
};

class OmpCycleAndExitChecker {
class AssociatedLoopChecker {
public:
OmpCycleAndExitChecker(SemanticsContext &context, std::int64_t level)
AssociatedLoopChecker(SemanticsContext &context, std::int64_t level)
: context_{context}, level_{level} {}

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

bool Pre(const parser::DoConstruct &dc) {
level_--;
const auto &constructName{std::get<0>(std::get<0>(dc.t).statement.t)};
const auto &doStmt{
std::get<parser::Statement<parser::NonLabelDoStmt>>(dc.t)};
const auto &constructName{
std::get<std::optional<parser::Name>>(doStmt.statement.t)};
if (constructName) {
constructNamesAndLevels_.emplace(
constructName.value().ToString(), level_);
}
if (level_ >= 0) {
if (dc.IsDoWhile()) {
context_.Say(doStmt.source,
"The associated loop of a loop-associated directive cannot be a DO WHILE."_err_en_US);
}
if (!dc.GetLoopControl()) {
context_.Say(doStmt.source,
"The associated loop of a loop-associated directive cannot be a DO without control."_err_en_US);
}
}
return true;
}

Expand Down Expand Up @@ -450,9 +463,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
const auto &doBlock{std::get<parser::Block>(doConstruct->t)};
CheckNoBranching(doBlock, beginDir.v, beginDir.source);
}
CheckDoWhile(x);
CheckLoopItrVariableIsInt(x);
CheckCycleConstraints(x);
CheckAssociatedLoopConstraints(x);
HasInvalidDistributeNesting(x);
if (CurrentDirectiveIsNested() &&
llvm::omp::topTeamsSet.test(GetContextParent().directive)) {
Expand All @@ -478,21 +490,6 @@ void OmpStructureChecker::SetLoopInfo(const parser::OpenMPLoopConstruct &x) {
}
}
}
void OmpStructureChecker::CheckDoWhile(const parser::OpenMPLoopConstruct &x) {
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
if (beginDir.v == llvm::omp::Directive::OMPD_do) {
if (const auto &doConstruct{
std::get<std::optional<parser::DoConstruct>>(x.t)}) {
if (doConstruct.value().IsDoWhile()) {
const auto &doStmt{std::get<parser::Statement<parser::NonLabelDoStmt>>(
doConstruct.value().t)};
context_.Say(doStmt.source,
"The DO loop cannot be a DO WHILE with DO directive."_err_en_US);
}
}
}
}

void OmpStructureChecker::CheckLoopItrVariableIsInt(
const parser::OpenMPLoopConstruct &x) {
Expand Down Expand Up @@ -647,8 +644,8 @@ std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
const auto &clauseList{std::get<parser::OmpClauseList>(beginLoopDir.t)};
std::int64_t orderedCollapseLevel{1};
std::int64_t orderedLevel{0};
std::int64_t collapseLevel{0};
std::int64_t orderedLevel{1};
std::int64_t collapseLevel{1};

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

void OmpStructureChecker::CheckCycleConstraints(
void OmpStructureChecker::CheckAssociatedLoopConstraints(
const parser::OpenMPLoopConstruct &x) {
std::int64_t ordCollapseLevel{GetOrdCollapseLevel(x)};
OmpCycleAndExitChecker checker{context_, ordCollapseLevel};
AssociatedLoopChecker checker{context_, ordCollapseLevel};
parser::Walk(x, checker);
}

Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Semantics/check-omp-structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class OmpStructureChecker

void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x);
void CheckDoWhile(const parser::OpenMPLoopConstruct &x);
void CheckCycleConstraints(const parser::OpenMPLoopConstruct &x);
void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
template <typename T, typename D> bool IsOperatorValid(const T &, const D &);
void CheckAtomicMemoryOrderClause(
const parser::OmpAtomicClauseList *, const parser::OmpAtomicClauseList *);
Expand Down
1 change: 1 addition & 0 deletions flang/test/Semantics/OpenMP/clause-validity01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
outer: do i=0, 10
inner: do j=1, 10
exit
!ERROR: EXIT statement terminates associated loop of an OpenMP DO construct
exit outer
!ERROR: EXIT to construct 'outofparallel' outside of PARALLEL construct is not allowed
!ERROR: EXIT to construct 'outofparallel' outside of DO construct is not allowed
Expand Down
1 change: 1 addition & 0 deletions flang/test/Semantics/OpenMP/do-collapse.f90
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ program omp_doCollapse
!$omp parallel do collapse(2)
do i = 1, 3
!ERROR: Loop control is not present in the DO LOOP
!ERROR: The associated loop of a loop-associated directive cannot be a DO without control.
do
end do
end do
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Semantics/OpenMP/do09.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
program omp_do
integer :: i = 0,k
!$omp do
!ERROR: The DO loop cannot be a DO WHILE with DO directive.
!ERROR: The associated loop of a loop-associated directive cannot be a DO WHILE.
do while (i <= 10)
print *, "it",i
i = i+1
end do
!$omp end do

!$omp do
!ERROR: The DO loop cannot be a DO WHILE with DO directive.
!ERROR: The associated loop of a loop-associated directive cannot be a DO WHILE.
do while (i <= 10)
do while (j <= 10)
print *, "it",k
Expand Down
Loading