[flang-commits] [flang] 24d21ca - [flang][OpenMP] Fix counting generated nests (#183957)

via flang-commits flang-commits at lists.llvm.org
Mon Mar 2 04:08:52 PST 2026


Author: Krzysztof Parzyszek
Date: 2026-03-02T06:08:48-06:00
New Revision: 24d21ca03cd2ba7792f72c5acad1d8715b622237

URL: https://github.com/llvm/llvm-project/commit/24d21ca03cd2ba7792f72c5acad1d8715b622237
DIFF: https://github.com/llvm/llvm-project/commit/24d21ca03cd2ba7792f72c5acad1d8715b622237.diff

LOG: [flang][OpenMP] Fix counting generated nests (#183957)

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.

Added: 
    flang/test/Semantics/OpenMP/fuse1.f90

Modified: 
    flang/lib/Semantics/check-omp-loop.cpp

Removed: 
    


################################################################################
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
+


        


More information about the flang-commits mailing list