Skip to content

Conversation

Meinersbur
Copy link
Member

PR #160283 uses Unwrap to detect a continue statement, but it applied it on the loop body itelf which sometimes finds a trailing continue statement, but not always. Apply Unwrap on the last body statement instead, where the continue is expected.

Fixes #161529

@Meinersbur Meinersbur requested a review from ronlieb October 1, 2025 17:26
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:openmp flang:semantics labels Oct 1, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 1, 2025

@llvm/pr-subscribers-flang-openmp

Author: Michael Kruse (Meinersbur)

Changes

PR #160283 uses Unwrap to detect a continue statement, but it applied it on the loop body itelf which sometimes finds a trailing continue statement, but not always. Apply Unwrap on the last body statement instead, where the continue is expected.

Fixes #161529


Full diff: https://github.com/llvm/llvm-project/pull/161554.diff

4 Files Affected:

  • (modified) flang/lib/Semantics/resolve-directives.cpp (+8-5)
  • (added) flang/test/Lower/OpenMP/wsloop-collapse-continue.f90 (+19)
  • (modified) flang/test/Semantics/OpenMP/do08.f90 (-1)
  • (modified) flang/test/Semantics/OpenMP/do13.f90 (-1)
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index bd7b8ac552fab..d32fa3eedae21 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2303,14 +2303,17 @@ void OmpAttributeVisitor::CheckPerfectNestAndRectangularLoop(
     }
 
     auto checkPerfectNest = [&, this]() {
-      auto blockSize = block.size();
-      if (blockSize <= 1)
+      if (block.empty())
         return;
+      auto last = block.end();
+      --last;
 
-      if (parser::Unwrap<parser::ContinueStmt>(x))
-        blockSize -= 1;
+      // A trailing CONTINUE or CYCLE does not belong to the loop body
+      if (parser::Unwrap<parser::ContinueStmt>(*last))
+        --last;
 
-      if (blockSize <= 1)
+      // In a perfectly nested loop, the nested loop must be the only statement
+      if (last == block.begin())
         return;
 
       // Non-perfectly nested loop
diff --git a/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90 b/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90
new file mode 100644
index 0000000000000..fea7a8b335d63
--- /dev/null
+++ b/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90
@@ -0,0 +1,19 @@
+! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
+
+program wsloop_collapse_continue
+  integer i, j
+
+! CHECK: omp.wsloop {{.*}} {
+! CHECK: omp.loop_nest ({{.*}}) : i32 = ({{.*}}) to ({{.*}}) inclusive step ({{.*}}) collapse(2) {
+  !$omp do collapse(2)
+  do 50 i = 1, 42
+     do 51 j = 1, 84
+! CHECK: fir.call @_FortranAioOutputInteger32(
+        print *, i
+! CHECK: fir.call @_FortranAioOutputInteger32(
+        print *, j
+     51 continue
+  50 continue
+  !$omp end do
+
+end program wsloop_collapse_continue
diff --git a/flang/test/Semantics/OpenMP/do08.f90 b/flang/test/Semantics/OpenMP/do08.f90
index bb3c1d0cd3855..5143dff0dd315 100644
--- a/flang/test/Semantics/OpenMP/do08.f90
+++ b/flang/test/Semantics/OpenMP/do08.f90
@@ -61,7 +61,6 @@ program omp
   !$omp end do
 
 
-  !ERROR: Canonical loop nest must be perfectly nested.
   !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
   !$omp do collapse(3)
   do 60 i=2,200,2
diff --git a/flang/test/Semantics/OpenMP/do13.f90 b/flang/test/Semantics/OpenMP/do13.f90
index 8f7844f4136f9..6e9d1dddade4c 100644
--- a/flang/test/Semantics/OpenMP/do13.f90
+++ b/flang/test/Semantics/OpenMP/do13.f90
@@ -59,7 +59,6 @@ program omp
   !$omp end do
 
 
-  !ERROR: Canonical loop nest must be perfectly nested.
   !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
   !$omp do collapse(3)
   do 60 i=1,10

@llvmbot
Copy link
Member

llvmbot commented Oct 1, 2025

@llvm/pr-subscribers-flang-fir-hlfir

Author: Michael Kruse (Meinersbur)

Changes

PR #160283 uses Unwrap to detect a continue statement, but it applied it on the loop body itelf which sometimes finds a trailing continue statement, but not always. Apply Unwrap on the last body statement instead, where the continue is expected.

Fixes #161529


Full diff: https://github.com/llvm/llvm-project/pull/161554.diff

4 Files Affected:

  • (modified) flang/lib/Semantics/resolve-directives.cpp (+8-5)
  • (added) flang/test/Lower/OpenMP/wsloop-collapse-continue.f90 (+19)
  • (modified) flang/test/Semantics/OpenMP/do08.f90 (-1)
  • (modified) flang/test/Semantics/OpenMP/do13.f90 (-1)
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index bd7b8ac552fab..d32fa3eedae21 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2303,14 +2303,17 @@ void OmpAttributeVisitor::CheckPerfectNestAndRectangularLoop(
     }
 
     auto checkPerfectNest = [&, this]() {
-      auto blockSize = block.size();
-      if (blockSize <= 1)
+      if (block.empty())
         return;
+      auto last = block.end();
+      --last;
 
-      if (parser::Unwrap<parser::ContinueStmt>(x))
-        blockSize -= 1;
+      // A trailing CONTINUE or CYCLE does not belong to the loop body
+      if (parser::Unwrap<parser::ContinueStmt>(*last))
+        --last;
 
-      if (blockSize <= 1)
+      // In a perfectly nested loop, the nested loop must be the only statement
+      if (last == block.begin())
         return;
 
       // Non-perfectly nested loop
diff --git a/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90 b/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90
new file mode 100644
index 0000000000000..fea7a8b335d63
--- /dev/null
+++ b/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90
@@ -0,0 +1,19 @@
+! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
+
+program wsloop_collapse_continue
+  integer i, j
+
+! CHECK: omp.wsloop {{.*}} {
+! CHECK: omp.loop_nest ({{.*}}) : i32 = ({{.*}}) to ({{.*}}) inclusive step ({{.*}}) collapse(2) {
+  !$omp do collapse(2)
+  do 50 i = 1, 42
+     do 51 j = 1, 84
+! CHECK: fir.call @_FortranAioOutputInteger32(
+        print *, i
+! CHECK: fir.call @_FortranAioOutputInteger32(
+        print *, j
+     51 continue
+  50 continue
+  !$omp end do
+
+end program wsloop_collapse_continue
diff --git a/flang/test/Semantics/OpenMP/do08.f90 b/flang/test/Semantics/OpenMP/do08.f90
index bb3c1d0cd3855..5143dff0dd315 100644
--- a/flang/test/Semantics/OpenMP/do08.f90
+++ b/flang/test/Semantics/OpenMP/do08.f90
@@ -61,7 +61,6 @@ program omp
   !$omp end do
 
 
-  !ERROR: Canonical loop nest must be perfectly nested.
   !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
   !$omp do collapse(3)
   do 60 i=2,200,2
diff --git a/flang/test/Semantics/OpenMP/do13.f90 b/flang/test/Semantics/OpenMP/do13.f90
index 8f7844f4136f9..6e9d1dddade4c 100644
--- a/flang/test/Semantics/OpenMP/do13.f90
+++ b/flang/test/Semantics/OpenMP/do13.f90
@@ -59,7 +59,6 @@ program omp
   !$omp end do
 
 
-  !ERROR: Canonical loop nest must be perfectly nested.
   !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
   !$omp do collapse(3)
   do 60 i=1,10

@llvmbot
Copy link
Member

llvmbot commented Oct 1, 2025

@llvm/pr-subscribers-flang-semantics

Author: Michael Kruse (Meinersbur)

Changes

PR #160283 uses Unwrap to detect a continue statement, but it applied it on the loop body itelf which sometimes finds a trailing continue statement, but not always. Apply Unwrap on the last body statement instead, where the continue is expected.

Fixes #161529


Full diff: https://github.com/llvm/llvm-project/pull/161554.diff

4 Files Affected:

  • (modified) flang/lib/Semantics/resolve-directives.cpp (+8-5)
  • (added) flang/test/Lower/OpenMP/wsloop-collapse-continue.f90 (+19)
  • (modified) flang/test/Semantics/OpenMP/do08.f90 (-1)
  • (modified) flang/test/Semantics/OpenMP/do13.f90 (-1)
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index bd7b8ac552fab..d32fa3eedae21 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2303,14 +2303,17 @@ void OmpAttributeVisitor::CheckPerfectNestAndRectangularLoop(
     }
 
     auto checkPerfectNest = [&, this]() {
-      auto blockSize = block.size();
-      if (blockSize <= 1)
+      if (block.empty())
         return;
+      auto last = block.end();
+      --last;
 
-      if (parser::Unwrap<parser::ContinueStmt>(x))
-        blockSize -= 1;
+      // A trailing CONTINUE or CYCLE does not belong to the loop body
+      if (parser::Unwrap<parser::ContinueStmt>(*last))
+        --last;
 
-      if (blockSize <= 1)
+      // In a perfectly nested loop, the nested loop must be the only statement
+      if (last == block.begin())
         return;
 
       // Non-perfectly nested loop
diff --git a/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90 b/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90
new file mode 100644
index 0000000000000..fea7a8b335d63
--- /dev/null
+++ b/flang/test/Lower/OpenMP/wsloop-collapse-continue.f90
@@ -0,0 +1,19 @@
+! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
+
+program wsloop_collapse_continue
+  integer i, j
+
+! CHECK: omp.wsloop {{.*}} {
+! CHECK: omp.loop_nest ({{.*}}) : i32 = ({{.*}}) to ({{.*}}) inclusive step ({{.*}}) collapse(2) {
+  !$omp do collapse(2)
+  do 50 i = 1, 42
+     do 51 j = 1, 84
+! CHECK: fir.call @_FortranAioOutputInteger32(
+        print *, i
+! CHECK: fir.call @_FortranAioOutputInteger32(
+        print *, j
+     51 continue
+  50 continue
+  !$omp end do
+
+end program wsloop_collapse_continue
diff --git a/flang/test/Semantics/OpenMP/do08.f90 b/flang/test/Semantics/OpenMP/do08.f90
index bb3c1d0cd3855..5143dff0dd315 100644
--- a/flang/test/Semantics/OpenMP/do08.f90
+++ b/flang/test/Semantics/OpenMP/do08.f90
@@ -61,7 +61,6 @@ program omp
   !$omp end do
 
 
-  !ERROR: Canonical loop nest must be perfectly nested.
   !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
   !$omp do collapse(3)
   do 60 i=2,200,2
diff --git a/flang/test/Semantics/OpenMP/do13.f90 b/flang/test/Semantics/OpenMP/do13.f90
index 8f7844f4136f9..6e9d1dddade4c 100644
--- a/flang/test/Semantics/OpenMP/do13.f90
+++ b/flang/test/Semantics/OpenMP/do13.f90
@@ -59,7 +59,6 @@ program omp
   !$omp end do
 
 
-  !ERROR: Canonical loop nest must be perfectly nested.
   !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
   !$omp do collapse(3)
   do 60 i=1,10

!$omp end do


!ERROR: Canonical loop nest must be perfectly nested.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These ERRORs were added in #60283. Those are still non-perfectly nested loops, but the other errors get precedence.

@Meinersbur Meinersbur merged commit 69a53b8 into llvm:main Oct 1, 2025
9 checks passed
searlmc1 pushed a commit to ROCm/llvm-project that referenced this pull request Oct 2, 2025
PR llvm#160283 uses `Unwrap` to detect a `continue` statement, but it
applied it on the loop body itelf which sometimes finds a trailing
continue statement, but not always. Apply `Unwrap` on the last body
statement instead, where the `continue` is expected.

Fixes llvm#161529
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Oct 3, 2025
PR llvm#160283 uses `Unwrap` to detect a `continue` statement, but it
applied it on the loop body itelf which sometimes finds a trailing
continue statement, but not always. Apply `Unwrap` on the last body
statement instead, where the `continue` is expected.

Fixes llvm#161529
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:fir-hlfir flang:openmp flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flang][openmp] Incorrect perfect nest detection if using continues instead of enddo.

3 participants