[flang-commits] [flang] a651871 - [flang] Keep a loop unstructured when its END DO is branched to from outside (#227597)

via flang-commits flang-commits at lists.llvm.org
Wed Sep 30 06:16:59 PDT 2026


Author: Kareem Ergawy
Date: 2026-09-30T15:16:52+02:00
New Revision: a651871a3f3f8aef58ae03d2fa81dcc1481b633c

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

LOG: [flang] Keep a loop unstructured when its END DO is branched to from outside (#227597)

A loop whose body branching is self-contained is lowered structurally,
with the body folded into a region. Its END DO is not part of that body:
it becomes the structured loop's terminator rather than a block of its
own. A branch from outside the loop targeting a label on the END DO
therefore had nothing to land on, and lowering crashed.

Such a loop no longer qualifies for that form. A branch from within the
body is unaffected: it is CYCLE-like and lands on the boundary the
structured form already provides.

Ran against the llvm-test-suite and the reported failure in
https://lab.llvm.org/buildbot/#/builders/198/builds/15502 and all green.

Added: 
    flang/test/Lower/do-loop-branch-to-loop-end.f90

Modified: 
    flang/lib/Lower/PFTBuilder.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 2f665a6cbf693..d1fbf4e07e313 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -2987,6 +2987,18 @@ static bool isStructurableWithUnstructuredInternals(
     if (!check(e))
       return false;
 
+  // Condition 2 reaches the EndDoStmt too, with a wider notion of "outside". A
+  // branch from the body to it is CYCLE-like and lands on the wrap's boundary,
+  // which the structured form expresses. A branch from outside the loop is a
+  // 
diff erent matter: the EndDoStmt is emitted as the structured loop's
+  // terminator, so no block is created for it and lowering has nothing to
+  // branch to.
+  if (auto it = unit.incomingBranches.find(&loop.evaluationList->back());
+      it != unit.incomingBranches.end())
+    for (const Fortran::lower::pft::Evaluation *src : it->second)
+      if (!isInLoopBody(src, loop))
+        return false;
+
   return true;
 }
 

diff  --git a/flang/test/Lower/do-loop-branch-to-loop-end.f90 b/flang/test/Lower/do-loop-branch-to-loop-end.f90
new file mode 100644
index 0000000000000..7f71b91c15321
--- /dev/null
+++ b/flang/test/Lower/do-loop-branch-to-loop-end.f90
@@ -0,0 +1,47 @@
+! RUN: bbc -emit-fir -o - %s | FileCheck %s
+
+! A loop whose body branching is self-contained keeps its structured form, with
+! the body folded into an scf.execute_region. The EndDoStmt is not part of that
+! body: it is emitted as the structured loop's terminator, so no block is
+! created for it.
+!
+! That is fine for a branch from the body, which is CYCLE-like and lands on the
+! wrap's boundary. A branch from outside the loop has nowhere to land, so such a
+! loop stays unstructured and is lowered as raw blocks.
+
+! The GOTO targets the EndDoStmt from outside the loop.
+subroutine branch_to_loop_end(a)
+  real :: a(10)
+  integer :: i
+  do i = 1, 10
+     a(i) = 0.0
+20 end do
+  go to 20
+end subroutine
+
+! CHECK-LABEL: func.func @_QPbranch_to_loop_end
+! Raw blocks, so the branch has a block to target.
+! CHECK:         cf.br ^bb1
+! CHECK:       ^bb1:
+! CHECK-NOT:     fir.do_loop
+! CHECK-NOT:     scf.execute_region
+
+! The same branch from inside the body is CYCLE-like, so the loop keeps its
+! structured form. The ASSIGN makes a body statement a new block, so the body is
+! wrapped.
+subroutine cycle_to_loop_end(a, b)
+  real :: a(10), b(10)
+  integer :: i, m
+  do 42 i = 1, 10
+     assign 41 to m
+41   a(i) = b(i)
+     go to 42
+42 end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPcycle_to_loop_end
+! CHECK:         fir.do_loop
+! CHECK:           scf.execute_region no_inline {
+! CHECK:             scf.yield
+! CHECK:           }
+! CHECK:         }


        


More information about the flang-commits mailing list