[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:11 PST 2026
https://github.com/jeanPerier created https://github.com/llvm/llvm-project/pull/184592
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.
>From b2a65301d9923031edd35f2d7c70470ef5bf42fc Mon Sep 17 00:00:00 2001
From: jeanPerier <jean.perier.polytechnique at gmail.com>
Date: Wed, 4 Mar 2026 12:23:55 +0100
Subject: [PATCH] Revert "[flang] make lowering to scf.while default (#184234)"
This reverts commit 62144f48d43fc33d7e73fff68aea31dd287d5349.
---
flang/lib/Lower/PFTBuilder.cpp | 10 ++++
flang/test/Lower/OpenMP/target.f90 | 15 ++----
flang/test/Lower/do-while-to-scf-while.f90 | 2 +-
flang/test/Lower/loops.f90 | 6 +--
flang/test/Lower/mixed_loops.f90 | 61 +++++++++++++---------
flang/test/Lower/pre-fir-tree02.f90 | 10 ++--
flang/test/Lower/while_loop.f90 | 33 ++++++------
7 files changed, 76 insertions(+), 61 deletions(-)
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>
More information about the flang-commits
mailing list