[flang-commits] [flang] [flang][OpenMP] Fix counting generated nests (PR #183957)
via flang-commits
flang-commits at lists.llvm.org
Sat Feb 28 13:10:49 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-openmp
Author: Krzysztof Parzyszek (kparzysz)
<details>
<summary>Changes</summary>
The code in `CountGeneratedNests` returned std::nullopt if the LOOPRANGE clause was not present on a FUSE construct. That is incorrect, the answer should be 1 instead, except in cases where the FUSE itself was invalid, such as having no loops nested in it.
Returning std::nullopt will not cause any messages to be emitted. The case of zero loops inside of FUSE will be diagnosed when analyzing the body of the FUSE construct itself, not when checking a construct in which the FUSE is nested.
This prevents error messages caused by the same problem from being emitted for every enclosing loop construct.
---
Full diff: https://github.com/llvm/llvm-project/pull/183957.diff
2 Files Affected:
- (modified) flang/lib/Semantics/check-omp-loop.cpp (+19-4)
- (added) flang/test/Semantics/OpenMP/fuse1.f90 (+18)
``````````diff
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 91b306a2a5ebd..de7a155dd96ef 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -281,6 +281,8 @@ static bool IsFullUnroll(const parser::OpenMPLoopConstruct &x) {
return false;
}
+// Count the number of loop nests generated by `epc`. This is just a helper
+// function for counting the number of loop nests in a parser::Block.
static std::optional<size_t> CountGeneratedNests(
const parser::ExecutionPartConstruct &epc) {
if (parser::Unwrap<parser::DoConstruct>(epc)) {
@@ -296,12 +298,26 @@ static std::optional<size_t> CountGeneratedNests(
return std::nullopt;
}
if (dir == llvm::omp::Directive::OMPD_fuse) {
+ auto nestedCount{CountGeneratedNests(std::get<parser::Block>(omp.t))};
+ // If there are no loops nested inside of FUSE, then the construct is
+ // invalid. This case will be diagnosed when analyzing the body of the FUSE
+ // construct itself, not when checking a construct in which the FUSE is
+ // nested.
+ // Returning std::nullopt prevents error messages caused by the same
+ // problem from being emitted for every enclosing loop construct, for
+ // example:
+ // !$omp do ! error: this should contain a loop (superfluous)
+ // !$omp fuse ! error: this should contain a loop
+ // !$omp end fuse
+ if (!nestedCount || *nestedCount == 0) {
+ return std::nullopt;
+ }
auto rangeAt{
llvm::find_if(beginSpec.Clauses().v, [](const parser::OmpClause &c) {
return c.Id() == llvm::omp::Clause::OMPC_looprange;
})};
if (rangeAt == beginSpec.Clauses().v.end()) {
- return std::nullopt;
+ return 1;
}
auto *loopRange{parser::Unwrap<parser::OmpLooprangeClause>(*rangeAt)};
@@ -309,9 +325,8 @@ static std::optional<size_t> CountGeneratedNests(
if (!count || *count <= 0) {
return std::nullopt;
}
- if (auto nestedCount{CountGeneratedNests(std::get<parser::Block>(omp.t))}) {
- if (static_cast<size_t>(*count) <= *nestedCount)
- return 1 + *nestedCount - static_cast<size_t>(*count);
+ if (static_cast<size_t>(*count) <= *nestedCount) {
+ return 1 + *nestedCount - static_cast<size_t>(*count);
}
return std::nullopt;
}
diff --git a/flang/test/Semantics/OpenMP/fuse1.f90 b/flang/test/Semantics/OpenMP/fuse1.f90
new file mode 100644
index 0000000000000..0616a3c52786d
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/fuse1.f90
@@ -0,0 +1,18 @@
+!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60
+
+! Make sure we correctly count the number of nests generated by FUSE
+! without a LOOPRANGE clause.
+
+subroutine f
+ integer :: i
+
+ !$omp do
+ !ERROR: The specified loop range requires 2 loops, but the loop sequence has a length of 1
+ !$omp fuse looprange(1, 2)
+ !$omp fuse
+ do i = 1, 10
+ end do
+ !$omp end fuse
+ !$omp end fuse
+end
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/183957
More information about the flang-commits
mailing list