Revert "[flang] make lowering to scf.while default" (#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](d0f50d5574/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.
This commit is contained in:
jeanPerier 2026-03-04 12:42:08 +01:00 committed by GitHub
parent 9c2829f2e1
commit ee8184573f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 76 additions and 61 deletions

View File

@ -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 @@ private:
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 &) {

View File

@ -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: }

View File

@ -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

View File

@ -147,12 +147,12 @@ end
! 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

View File

@ -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>

View File

@ -82,15 +82,15 @@ program test_prog
! 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

View File

@ -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>