[flang-commits] [flang] [flang][cuda] Avoid crash when the force modifier is used (PR #160176)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Mon Sep 22 11:51:08 PDT 2025
https://github.com/clementval created https://github.com/llvm/llvm-project/pull/160176
When the force modifier is used on the collapse clause, statements can appear between the nested loops. Update the `getNextDoConstruct` lambda to take this into account.
Note that the force collapse modifier triggers a TODO later in lowering.
>From c325c64b4f80febbdde4e6c6400fbe504d363f2f Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 22 Sep 2025 11:49:14 -0700
Subject: [PATCH] [flang][cuda] Avoid crash when the force modifier is used
---
flang/lib/Semantics/resolve-directives.cpp | 27 ++++++++++++++-----
.../Semantics/OpenACC/acc-collapse-force.f90 | 19 +++++++++++++
2 files changed, 40 insertions(+), 6 deletions(-)
create mode 100644 flang/test/Semantics/OpenACC/acc-collapse-force.f90
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index caee3af8a7ca1..dd0a94f0b816f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -315,6 +315,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
private:
std::int64_t GetAssociatedLoopLevelFromClauses(const parser::AccClauseList &);
+ bool HasForceCollapseModifier(const parser::AccClauseList &);
Symbol::Flags dataSharingAttributeFlags{Symbol::Flag::AccShared,
Symbol::Flag::AccPrivate, Symbol::Flag::AccFirstPrivate,
@@ -333,7 +334,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
Symbol::Flag::AccDevicePtr, Symbol::Flag::AccDeviceResident,
Symbol::Flag::AccLink, Symbol::Flag::AccPresent};
- void CheckAssociatedLoop(const parser::DoConstruct &);
+ void CheckAssociatedLoop(const parser::DoConstruct &, bool forceCollapsed);
void ResolveAccObjectList(const parser::AccObjectList &, Symbol::Flag);
void ResolveAccObject(const parser::AccObject &, Symbol::Flag);
Symbol *ResolveAcc(const parser::Name &, Symbol::Flag, Scope &);
@@ -1168,7 +1169,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCLoopConstruct &x) {
ClearDataSharingAttributeObjects();
SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
- CheckAssociatedLoop(*outer);
+ CheckAssociatedLoop(*outer, HasForceCollapseModifier(clauseList));
return true;
}
@@ -1366,7 +1367,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
const auto &clauseList{std::get<parser::AccClauseList>(beginBlockDir.t)};
SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
- CheckAssociatedLoop(*outer);
+ CheckAssociatedLoop(*outer, HasForceCollapseModifier(clauseList));
ClearDataSharingAttributeObjects();
return true;
}
@@ -1478,6 +1479,18 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
return true;
}
+bool AccAttributeVisitor::HasForceCollapseModifier(
+ const parser::AccClauseList &x) {
+ for (const auto &clause : x.v) {
+ if (const auto *collapseClause{
+ std::get_if<parser::AccClause::Collapse>(&clause.u)}) {
+ const parser::AccCollapseArg &arg = collapseClause->v;
+ return std::get<bool>(arg.t);
+ }
+ }
+ return false;
+}
+
std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
const parser::AccClauseList &x) {
std::int64_t collapseLevel{0};
@@ -1499,14 +1512,14 @@ std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
}
void AccAttributeVisitor::CheckAssociatedLoop(
- const parser::DoConstruct &outerDoConstruct) {
+ const parser::DoConstruct &outerDoConstruct, bool forceCollapsed) {
std::int64_t level{GetContext().associatedLoopLevel};
if (level <= 0) { // collapse value was negative or 0
return;
}
const auto getNextDoConstruct =
- [this](const parser::Block &block,
+ [this, forceCollapsed](const parser::Block &block,
std::int64_t &level) -> const parser::DoConstruct * {
for (const auto &entry : block) {
if (const auto *doConstruct = GetDoConstructIf(entry)) {
@@ -1524,7 +1537,9 @@ void AccAttributeVisitor::CheckAssociatedLoop(
"LOOP directive not expected in COLLAPSE loop nest"_err_en_US);
level = 0;
} else {
- break;
+ if (!forceCollapsed) {
+ break;
+ }
}
}
return nullptr;
diff --git a/flang/test/Semantics/OpenACC/acc-collapse-force.f90 b/flang/test/Semantics/OpenACC/acc-collapse-force.f90
new file mode 100644
index 0000000000000..80b1060ebe6c7
--- /dev/null
+++ b/flang/test/Semantics/OpenACC/acc-collapse-force.f90
@@ -0,0 +1,19 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenacc -fsyntax-only
+
+! Check that loop with force collapse do not break in the semantic step.
+subroutine sub3()
+ integer :: i, j
+ integer, parameter :: n = 100, m = 200
+ real, dimension(n, m) :: a
+ real, dimension(n) :: bb
+ real :: r
+ a = 1
+ r = 0
+ !$acc parallel loop collapse(force:2) copy(a)
+ do i = 1, n
+ bb(i) = r
+ do j = 1, m
+ a(i,j) = r * a(i,j)
+ enddo
+ enddo
+end subroutine
More information about the flang-commits
mailing list