[flang-commits] [flang] Revert "[flang] make lowering to scf.while default" (PR #184592)

via flang-commits flang-commits at lists.llvm.org
Wed Mar 4 03:28:44 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-openmp

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

Author: None (jeanPerier)

<details>
<summary>Changes</summary>

Reverts llvm/llvm-project#<!-- -->184234

This is breaking SPEC and other tests.

Reproducer:

```
subroutine foo()
  logical :: l1, l2
  do while (l1())
    if (l2()) then
      call bar()
    endif
  enddo
end
```

The cause is a pass ordering issue between the SCFToControlFlowPass and CfgConversionPass [here](https://github.com/llvm/llvm-project/blob/d0f50d55746aa27e6467cb2bce66596da9da065b/flang/lib/Optimizer/Passes/Pipelines.cpp#L239-L240).

I think they need to be run simultaneously somehow because the both SCF and FIR structured operations may contain each other, and none will be happy to get block CFG generated inside their region by the pass lowering the other.

Reverting while this is sorted out.

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


7 Files Affected:

- (modified) flang/lib/Lower/PFTBuilder.cpp (+10) 
- (modified) flang/test/Lower/OpenMP/target.f90 (+3-12) 
- (modified) flang/test/Lower/do-while-to-scf-while.f90 (+1-1) 
- (modified) flang/test/Lower/loops.f90 (+3-3) 
- (modified) flang/test/Lower/mixed_loops.f90 (+36-25) 
- (modified) flang/test/Lower/pre-fir-tree02.f90 (+5-5) 
- (modified) flang/test/Lower/while_loop.f90 (+18-15) 


``````````diff
diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 2622e1a2128b4..7e9f8b5de0827 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -28,6 +28,10 @@ static llvm::cl::opt<bool> clDisableStructuredFir(
 using namespace Fortran;
 
 namespace {
+static llvm::cl::opt<bool> lowerDoWhileToSCFWhile(
+    "lower-do-while-to-scf-while", llvm::cl::init(false),
+    llvm::cl::desc("lower structured DO WHILE loops to scf.while"),
+    llvm::cl::Hidden);
 /// Helpers to unveil parser node inside Fortran::parser::Statement<>,
 /// Fortran::parser::UnlabeledStatement, and Fortran::common::Indirection<>
 template <typename A>
@@ -1058,6 +1062,12 @@ class PFTBuilder {
               if (bounds->Name().thing.symbol->GetType()->IsNumeric(
                       common::TypeCategory::Real))
                 eval.isUnstructured = true; // real-valued loop control
+            } else if (std::get_if<parser::ScalarLogicalExpr>(
+                           &loopControl->u)) {
+              // Leave DO WHILE structured when -lower-do-while-to-scf-while is
+              // enabled; branch analysis will mark unstructured cases.
+              if (!lowerDoWhileToSCFWhile)
+                eval.isUnstructured = true; // while loop
             }
           },
           [&](const parser::EndDoStmt &) {
diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90
index 09fd5498c018a..e7168f3944037 100644
--- a/flang/test/Lower/OpenMP/target.f90
+++ b/flang/test/Lower/OpenMP/target.f90
@@ -684,21 +684,12 @@ subroutine target_unstructured
       !CHECK-NO-FPRIV: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtarget_unstructuredEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
       !CHECK-NO-FPRIV: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFtarget_unstructuredEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 
-      !CHECK: scf.while : () -> () {
-      !CHECK:   %[[I_CUR:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32>
-      !CHECK:   %[[J_CUR:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32>
-      !CHECK:   %[[COND:.*]] = arith.cmpi sle, %[[I_CUR]], %[[J_CUR]] : i32
-      !CHECK:   scf.condition(%[[COND]])
-      !CHECK: } do {
-      !CHECK:   %[[I_BODY:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32>
-      !CHECK:   %[[ONE:.*]] = arith.constant 1 : i32
-      !CHECK:   %[[I_NEXT:.*]] = arith.addi %[[I_BODY]], %[[ONE]] : i32
-      !CHECK:   hlfir.assign %[[I_NEXT]] to %[[VAL_8]]#0 : i32, !fir.ref<i32>
-      !CHECK:   scf.yield
-      !CHECK: }
+      !CHECK: ^bb1:
       do while (i <= j)
+         !CHECK: ^bb2:
          i = i + 1
       end do
+      !CHECK: ^bb3:
       !CHECK: omp.terminator
    !$omp end target
    !CHECK: }
diff --git a/flang/test/Lower/do-while-to-scf-while.f90 b/flang/test/Lower/do-while-to-scf-while.f90
index 6f5dfc7359e37..6d057ed823c36 100644
--- a/flang/test/Lower/do-while-to-scf-while.f90
+++ b/flang/test/Lower/do-while-to-scf-while.f90
@@ -1,4 +1,4 @@
-! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc -emit-hlfir -lower-do-while-to-scf-while %s -o - | FileCheck %s
 
 ! CHECK-LABEL: func.func @_QPsimple_do_while()
 ! CHECK: scf.while
diff --git a/flang/test/Lower/loops.f90 b/flang/test/Lower/loops.f90
index 87d30e24fd3f7..5ee6562733dae 100644
--- a/flang/test/Lower/loops.f90
+++ b/flang/test/Lower/loops.f90
@@ -147,12 +147,12 @@ subroutine lis(n)
 ! CHECK-LABEL: print_nothing
 subroutine print_nothing(k1, k2)
   if (k1 > 0) then
-    ! CHECK: scf.while : () -> () {
-    ! CHECK: scf.condition
+    ! CHECK: br [[header:\^bb[0-9]+]]
+    ! CHECK: [[header]]
     do while (k1 > k2)
       print*, k1, k2 ! no output
       k2 = k2 + 1
-      ! CHECK: scf.yield
+      ! CHECK: br [[header]]
     end do
   end if
 end
diff --git a/flang/test/Lower/mixed_loops.f90 b/flang/test/Lower/mixed_loops.f90
index 396726b030875..11534ae9490d0 100644
--- a/flang/test/Lower/mixed_loops.f90
+++ b/flang/test/Lower/mixed_loops.f90
@@ -3,6 +3,7 @@
 ! Test while loop inside do loop.
 ! CHECK-LABEL: while_inside_do_loop
 subroutine while_inside_do_loop
+  ! CHECK-DAG: %[[T_REF:.*]] = fir.alloca i32
   ! CHECK-DAG: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFwhile_inside_do_loopEi"}
   ! CHECK-DAG: %[[I:.*]]:2 = hlfir.declare %[[I_ADDR]]
   ! CHECK-DAG: %[[J_ADDR:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFwhile_inside_do_loopEj"}
@@ -11,40 +12,52 @@ subroutine while_inside_do_loop
 
   ! CHECK-DAG: %[[C8:.*]] = arith.constant 8 : i32
   ! CHECK-DAG: %[[C13:.*]] = arith.constant 13 : i32
-  ! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
-  ! CHECK-DAG: %[[LB:.*]] = fir.convert %[[C8]] : (i32) -> index
-  ! CHECK-DAG: %[[UB:.*]] = fir.convert %[[C13]] : (i32) -> index
-  ! CHECK-DAG: %[[INIT:.*]] = fir.convert %[[LB]] : (index) -> i32
-  ! CHECK: %[[RES:.*]] = fir.do_loop %{{.*}} = %[[LB]] to %[[UB]] step %[[C1]] iter_args(%[[I_IV:.*]] = %[[INIT]]) -> (i32) {
-  ! CHECK:   fir.store %[[I_IV]] to %[[I]]#0 : !fir.ref<i32>
+  ! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C13]], %[[C8]] : i32
+  ! CHECK: %[[RANGE:.*]] = arith.addi %[[DIFF]], %[[C1]] : i32
+  ! CHECK: %[[HIGH:.*]] = arith.divsi %[[RANGE]], %[[C1]] : i32
+  ! CHECK: fir.store %[[HIGH]] to %[[T_REF]] : !fir.ref<i32>
+  ! CHECK: fir.store %[[C8]] to %[[I]]#0 : !fir.ref<i32>
+
+  ! CHECK: cf.br ^[[HDR1:.*]]
+  ! CHECK: ^[[HDR1]]:  // 2 preds: ^{{.*}}, ^[[EXIT2:.*]]
+  ! CHECK: %[[T:.*]] = fir.load %[[T_REF]] : !fir.ref<i32>
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[T]], %[[C0]] : i32
+  ! CHECK: cf.cond_br %[[COND]], ^[[BODY1:.*]], ^[[EXIT1:.*]]
   do i=8,13
+    ! CHECK: ^[[BODY1]]:  // pred: ^[[HDR1]]
     ! CHECK: %[[C3:.*]] = arith.constant 3 : i32
     ! CHECK: hlfir.assign %[[C3]] to %[[J]]#0 : i32, !fir.ref<i32>
     j=3
 
-    ! CHECK: scf.while : () -> () {
+    ! CHECK: cf.br ^[[HDR2:.*]]
+    ! CHECK: ^[[HDR2]]:  // 2 preds: ^[[BODY1]], ^[[BODY2:.*]]
     ! CHECK: %[[JVAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
     ! CHECK: %[[IVAL:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
     ! CHECK: %[[COND2:.*]] = arith.cmpi slt, %[[JVAL]], %[[IVAL]] : i32
-    ! CHECK: scf.condition(%[[COND2]])
-    ! CHECK: } do {
+    ! CHECK: cf.cond_br %[[COND2]], ^[[BODY2:.*]], ^[[EXIT2]]
     do while (j .lt. i)
+      ! CHECK: ^[[BODY2]]:  // pred: ^[[HDR2]]
       ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
       ! CHECK: %[[JVAL2:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
       ! CHECK: %[[INC2:.*]] = arith.muli %[[C2]], %[[JVAL2]] : i32
       ! CHECK: hlfir.assign %[[INC2]] to %[[J]]#0 : i32, !fir.ref<i32>
       j=j*2
-    ! CHECK: scf.yield
+    ! CHECK: cf.br ^[[HDR2]]
     end do
-    ! CHECK: }
 
-  ! CHECK: %[[STEP_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
-  ! CHECK: %[[I_CUR:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
-  ! CHECK: %[[I_NEXT:.*]] = arith.addi %[[I_CUR]], %[[STEP_I32]] overflow<nsw> : i32
-  ! CHECK: fir.result %[[I_NEXT]] : i32
-  ! CHECK: fir.store %[[RES]] to %[[I]]#0 : !fir.ref<i32>
+  ! CHECK: ^[[EXIT2]]: // pred: ^[[HDR2]]
+  ! CHECK: %[[T2:.*]] = fir.load %[[T_REF]] : !fir.ref<i32>
+  ! CHECK: %[[TDEC:.*]] = arith.subi %[[T2]], {{.*}} : i32
+  ! CHECK: fir.store %[[TDEC]] to %[[T_REF]]
+  ! CHECK: %[[I3:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
+  ! CHECK: %[[IINC:.*]] = arith.addi %[[I3]], {{.*}} overflow<nsw> : i32
+  ! CHECK: fir.store %[[IINC]] to %[[I]]#0 : !fir.ref<i32>
+  ! CHECK: cf.br ^[[HDR1]]
   end do
 
+  ! CHECK: ^[[EXIT1]]:  // pred: ^[[HDR1]]
   ! CHECK: %[[IPRINT:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
   ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[IPRINT]])
   ! CHECK: %[[JPRINT:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
@@ -65,21 +78,19 @@ subroutine do_inside_while_loop
     ! CHECK: hlfir.assign %[[C3]] to %[[J]]#0 : i32, !fir.ref<i32>
     j=3
 
-    ! CHECK: scf.while : () -> () {
+    ! CHECK: cf.br ^[[HDR1:.*]]
+    ! CHECK: ^[[HDR1]]:  // 2 preds: ^{{.*}}, ^[[BODY1:.*]]
     ! CHECK: %[[JVAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
     ! CHECK: %[[UL:.*]] = arith.constant 21 : i32
     ! CHECK: %[[COND:.*]] = arith.cmpi slt, %[[JVAL]], %[[UL]] : i32
-    ! CHECK: scf.condition(%[[COND]])
-    ! CHECK: } do {
+    ! CHECK: cf.cond_br %[[COND]], ^[[BODY1]], ^[[EXIT1:.*]]
     do while (j .lt. 21)
+      ! CHECK: ^[[BODY1]]:  // pred: ^[[HDR1]]
 
       ! CHECK-DAG: %[[C8:.*]] = arith.constant 8 : i32
       ! CHECK-DAG: %[[C13:.*]] = arith.constant 13 : i32
       ! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
-      ! CHECK-DAG: %[[LB:.*]] = fir.convert %[[C8]] : (i32) -> index
-      ! CHECK-DAG: %[[UB:.*]] = fir.convert %[[C13]] : (i32) -> index
-      ! CHECK-DAG: %[[INIT:.*]] = fir.convert %[[LB]] : (index) -> i32
-      ! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %[[LB]] to %[[UB]] step %[[C1]] iter_args(%[[I_IV:.*]] = %[[INIT]]) -> (i32) {
+      ! CHECK: %{{.*}} = fir.do_loop %{{.*}} = {{.*}} to {{.*}} step {{.*}} iter_args(%[[I_IV:.*]] = {{.*}}) -> (i32) {
         ! CHECK: fir.store %[[I_IV]] to %[[I]]#0 : !fir.ref<i32>
         ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
         ! CHECK: %[[J2VAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
@@ -94,10 +105,10 @@ subroutine do_inside_while_loop
       ! CHECK: fir.store %{{.*}} to %[[I]]#0 : !fir.ref<i32>
       end do
 
-    ! CHECK: scf.yield
+    ! CHECK: cf.br ^[[HDR1]]
     end do
-  ! CHECK: }
 
+  ! CHECK: ^[[EXIT1]]:  // pred: ^[[HDR1]]
   ! CHECK: %[[IPRINT:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
   ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[IPRINT]])
   ! CHECK: %[[JPRINT:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
diff --git a/flang/test/Lower/pre-fir-tree02.f90 b/flang/test/Lower/pre-fir-tree02.f90
index 01f28f9d5c9aa..d61dc801eea60 100644
--- a/flang/test/Lower/pre-fir-tree02.f90
+++ b/flang/test/Lower/pre-fir-tree02.f90
@@ -82,15 +82,15 @@ subroutine incr(i)
       ! CHECK: CaseStmt
       case default
         ! Note: label-do-loop are canonicalized into do constructs
-        ! CHECK: <<DoConstruct>>
-        ! CHECK: [[DO_HDR:[0-9]+]] NonLabelDoStmt -> [[DO_END:[0-9]+]]: do 22 while(l<=k)
+        ! CHECK: <<DoConstruct!>>
+        ! CHECK: NonLabelDoStmt
         do 22 while(l<=k)
           ! CHECK: IfStmt
           if (p(l)<0.) p(l)=cos(p(l))
-          ! CHECK: [[CALL_ID:[0-9]+]] CallStmt: 22 call incr(l)
+          ! CHECK: CallStmt
 22        call incr(l)
-        ! CHECK: [[DO_END]] EndDoStmt -> [[DO_HDR]]
-       ! CHECK: <<End DoConstruct>>
+        ! CHECK: EndDoStmt
+       ! CHECK: <<End DoConstruct!>>
       ! CHECK: CaseStmt
       case (100:)
     ! CHECK: EndSelectStmt
diff --git a/flang/test/Lower/while_loop.f90 b/flang/test/Lower/while_loop.f90
index d68697e910cf0..8114394a39919 100644
--- a/flang/test/Lower/while_loop.f90
+++ b/flang/test/Lower/while_loop.f90
@@ -11,22 +11,23 @@ subroutine simple_loop
   ! CHECK: hlfir.assign %[[C5]] to %[[I]]#0
   i = 5
 
-  ! CHECK: scf.while : () -> () {
+  ! CHECK: cf.br ^[[BB1:.*]]
+  ! CHECK: ^[[BB1]]:  // 2 preds: ^{{.*}}, ^[[BB2:.*]]
   ! CHECK: %[[IVAL:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
   ! CHECK: %[[C1:.*]] = arith.constant 1 : i32
   ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[IVAL]], %[[C1]] : i32
-  ! CHECK: scf.condition(%[[COND]])
-  ! CHECK: } do {
+  ! CHECK: cf.cond_br %[[COND]], ^[[BB2]], ^[[BB3:.*]]
+  ! CHECK: ^[[BB2]]:  // pred: ^[[BB1]]
   ! CHECK: %[[IVAL2:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
   ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
   ! CHECK: %[[INC:.*]] = arith.subi %[[IVAL2]], %[[C2]] : i32
   ! CHECK: hlfir.assign %[[INC]] to %[[I]]#0 : i32, !fir.ref<i32>
-  ! CHECK: scf.yield
-  ! CHECK: }
+  ! CHECK: cf.br ^[[BB1]]
   do while (i .gt. 1)
     i = i - 2
   end do
 
+  ! CHECK: ^[[BB3]]:  // pred: ^[[BB1]]
   ! CHECK: %[[IVAL3:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
   ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[IVAL3]])
   print *, i
@@ -45,13 +46,14 @@ subroutine while_inside_while_loop
   ! CHECK: hlfir.assign %[[C13]] to %[[I]]#0
   i = 13
 
-  ! CHECK: scf.while : () -> () {
+  ! CHECK: cf.br ^[[HDR1:.*]]
+  ! CHECK: ^[[HDR1]]:  // 2 preds: ^{{.*}}, ^[[EXIT2:.*]]
   ! CHECK: %[[IVAL:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
   ! CHECK: %[[C8:.*]] = arith.constant 8 : i32
   ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[IVAL]], %[[C8]] : i32
-  ! CHECK: scf.condition(%[[COND]])
-  ! CHECK: } do {
+  ! CHECK: cf.cond_br %[[COND]], ^[[BODY1:.*]], ^[[EXIT1:.*]]
   do while (i .gt. 8)
+    ! CHECK: ^[[BODY1]]:  // pred: ^[[HDR1]]
     ! CHECK: %[[IVAL2:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
     ! CHECK: %[[C5:.*]] = arith.constant 5 : i32
     ! CHECK: %[[INC:.*]] = arith.subi %[[IVAL2]], %[[C5]] : i32
@@ -62,26 +64,27 @@ subroutine while_inside_while_loop
     ! CHECK: hlfir.assign %[[C3]] to %[[J]]#0
     j = 3
 
-    ! CHECK: scf.while : () -> () {
+    ! CHECK: cf.br ^[[HDR2:.*]]
+    ! CHECK: ^[[HDR2]]:  // 2 preds: ^[[BODY1]], ^[[BODY2:.*]]
     ! CHECK: %[[JVAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
     ! CHECK: %[[IVAL3:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
     ! CHECK: %[[COND2:.*]] = arith.cmpi slt, %[[JVAL]], %[[IVAL3]] : i32
-    ! CHECK: scf.condition(%[[COND2]])
-    ! CHECK: } do {
+    ! CHECK: cf.cond_br %[[COND2]], ^[[BODY2]], ^[[EXIT2:.*]]
     do while (j .lt. i)
+      ! CHECK: ^[[BODY2]]:  // pred: ^[[HDR2]]
       ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
       ! CHECK: %[[JVAL2:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
       ! CHECK: %[[INC2:.*]] = arith.muli %[[C2]], %[[JVAL2]] : i32
       ! CHECK: hlfir.assign %[[INC2]] to %[[J]]#0 : i32, !fir.ref<i32>
       j = j * 2
-    ! CHECK: scf.yield
+    ! CHECK: cf.br ^[[HDR2]]
     end do
-    ! CHECK: }
 
-    ! CHECK: scf.yield
+    ! CHECK: ^[[EXIT2]]: // pred: ^[[HDR2]]
+    ! CHECK: cf.br ^[[HDR1]]
   end do
-  ! CHECK: }
 
+  ! CHECK: ^[[EXIT1]]:  // pred: ^[[HDR1]]
   ! CHECK: %[[IPRINT:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
   ! CHECK: fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[IPRINT]])
   ! CHECK: %[[JPRINT:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>

``````````

</details>


https://github.com/llvm/llvm-project/pull/184592


More information about the flang-commits mailing list