[flang] make lowering to scf.while default (#184234)
We've tested the implementation of fortran do-while loops being lowered to scf.while and want to make it the default option.
This commit is contained in:
parent
393bbd5520
commit
62144f48d4
@ -28,10 +28,6 @@ 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>
|
||||
@ -1062,12 +1058,6 @@ 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 &) {
|
||||
|
||||
@ -684,12 +684,21 @@ 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: ^bb1:
|
||||
!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: }
|
||||
do while (i <= j)
|
||||
!CHECK: ^bb2:
|
||||
i = i + 1
|
||||
end do
|
||||
!CHECK: ^bb3:
|
||||
!CHECK: omp.terminator
|
||||
!$omp end target
|
||||
!CHECK: }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
! RUN: bbc -emit-hlfir -lower-do-while-to-scf-while %s -o - | FileCheck %s
|
||||
! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
|
||||
|
||||
! CHECK-LABEL: func.func @_QPsimple_do_while()
|
||||
! CHECK: scf.while
|
||||
|
||||
@ -147,12 +147,12 @@ end
|
||||
! CHECK-LABEL: print_nothing
|
||||
subroutine print_nothing(k1, k2)
|
||||
if (k1 > 0) then
|
||||
! CHECK: br [[header:\^bb[0-9]+]]
|
||||
! CHECK: [[header]]
|
||||
! CHECK: scf.while : () -> () {
|
||||
! CHECK: scf.condition
|
||||
do while (k1 > k2)
|
||||
print*, k1, k2 ! no output
|
||||
k2 = k2 + 1
|
||||
! CHECK: br [[header]]
|
||||
! CHECK: scf.yield
|
||||
end do
|
||||
end if
|
||||
end
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
! 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"}
|
||||
@ -12,52 +11,40 @@ 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 : 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:.*]]
|
||||
! 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>
|
||||
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: cf.br ^[[HDR2:.*]]
|
||||
! CHECK: ^[[HDR2]]: // 2 preds: ^[[BODY1]], ^[[BODY2:.*]]
|
||||
! CHECK: scf.while : () -> () {
|
||||
! 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: cf.cond_br %[[COND2]], ^[[BODY2:.*]], ^[[EXIT2]]
|
||||
! CHECK: scf.condition(%[[COND2]])
|
||||
! CHECK: } do {
|
||||
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: cf.br ^[[HDR2]]
|
||||
! CHECK: scf.yield
|
||||
end do
|
||||
! CHECK: }
|
||||
|
||||
! 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]]
|
||||
! 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>
|
||||
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>
|
||||
@ -78,19 +65,21 @@ subroutine do_inside_while_loop
|
||||
! CHECK: hlfir.assign %[[C3]] to %[[J]]#0 : i32, !fir.ref<i32>
|
||||
j=3
|
||||
|
||||
! CHECK: cf.br ^[[HDR1:.*]]
|
||||
! CHECK: ^[[HDR1]]: // 2 preds: ^{{.*}}, ^[[BODY1:.*]]
|
||||
! CHECK: scf.while : () -> () {
|
||||
! CHECK: %[[JVAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
|
||||
! CHECK: %[[UL:.*]] = arith.constant 21 : i32
|
||||
! CHECK: %[[COND:.*]] = arith.cmpi slt, %[[JVAL]], %[[UL]] : i32
|
||||
! CHECK: cf.cond_br %[[COND]], ^[[BODY1]], ^[[EXIT1:.*]]
|
||||
! CHECK: scf.condition(%[[COND]])
|
||||
! CHECK: } do {
|
||||
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: %{{.*}} = fir.do_loop %{{.*}} = {{.*}} to {{.*}} step {{.*}} iter_args(%[[I_IV:.*]] = {{.*}}) -> (i32) {
|
||||
! 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.store %[[I_IV]] to %[[I]]#0 : !fir.ref<i32>
|
||||
! CHECK: %[[C2:.*]] = arith.constant 2 : i32
|
||||
! CHECK: %[[J2VAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
|
||||
@ -105,10 +94,10 @@ subroutine do_inside_while_loop
|
||||
! CHECK: fir.store %{{.*}} to %[[I]]#0 : !fir.ref<i32>
|
||||
end do
|
||||
|
||||
! CHECK: cf.br ^[[HDR1]]
|
||||
! CHECK: scf.yield
|
||||
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>
|
||||
|
||||
@ -82,15 +82,15 @@ program test_prog
|
||||
! CHECK: CaseStmt
|
||||
case default
|
||||
! Note: label-do-loop are canonicalized into do constructs
|
||||
! CHECK: <<DoConstruct!>>
|
||||
! CHECK: NonLabelDoStmt
|
||||
! CHECK: <<DoConstruct>>
|
||||
! CHECK: [[DO_HDR:[0-9]+]] NonLabelDoStmt -> [[DO_END:[0-9]+]]: do 22 while(l<=k)
|
||||
do 22 while(l<=k)
|
||||
! CHECK: IfStmt
|
||||
if (p(l)<0.) p(l)=cos(p(l))
|
||||
! CHECK: CallStmt
|
||||
! CHECK: [[CALL_ID:[0-9]+]] CallStmt: 22 call incr(l)
|
||||
22 call incr(l)
|
||||
! CHECK: EndDoStmt
|
||||
! CHECK: <<End DoConstruct!>>
|
||||
! CHECK: [[DO_END]] EndDoStmt -> [[DO_HDR]]
|
||||
! CHECK: <<End DoConstruct>>
|
||||
! CHECK: CaseStmt
|
||||
case (100:)
|
||||
! CHECK: EndSelectStmt
|
||||
|
||||
@ -11,23 +11,22 @@ subroutine simple_loop
|
||||
! CHECK: hlfir.assign %[[C5]] to %[[I]]#0
|
||||
i = 5
|
||||
|
||||
! CHECK: cf.br ^[[BB1:.*]]
|
||||
! CHECK: ^[[BB1]]: // 2 preds: ^{{.*}}, ^[[BB2:.*]]
|
||||
! CHECK: scf.while : () -> () {
|
||||
! CHECK: %[[IVAL:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
|
||||
! CHECK: %[[C1:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[IVAL]], %[[C1]] : i32
|
||||
! CHECK: cf.cond_br %[[COND]], ^[[BB2]], ^[[BB3:.*]]
|
||||
! CHECK: ^[[BB2]]: // pred: ^[[BB1]]
|
||||
! CHECK: scf.condition(%[[COND]])
|
||||
! CHECK: } do {
|
||||
! 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: cf.br ^[[BB1]]
|
||||
! CHECK: scf.yield
|
||||
! CHECK: }
|
||||
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
|
||||
@ -46,14 +45,13 @@ subroutine while_inside_while_loop
|
||||
! CHECK: hlfir.assign %[[C13]] to %[[I]]#0
|
||||
i = 13
|
||||
|
||||
! CHECK: cf.br ^[[HDR1:.*]]
|
||||
! CHECK: ^[[HDR1]]: // 2 preds: ^{{.*}}, ^[[EXIT2:.*]]
|
||||
! CHECK: scf.while : () -> () {
|
||||
! CHECK: %[[IVAL:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
|
||||
! CHECK: %[[C8:.*]] = arith.constant 8 : i32
|
||||
! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[IVAL]], %[[C8]] : i32
|
||||
! CHECK: cf.cond_br %[[COND]], ^[[BODY1:.*]], ^[[EXIT1:.*]]
|
||||
! CHECK: scf.condition(%[[COND]])
|
||||
! CHECK: } do {
|
||||
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
|
||||
@ -64,27 +62,26 @@ subroutine while_inside_while_loop
|
||||
! CHECK: hlfir.assign %[[C3]] to %[[J]]#0
|
||||
j = 3
|
||||
|
||||
! CHECK: cf.br ^[[HDR2:.*]]
|
||||
! CHECK: ^[[HDR2]]: // 2 preds: ^[[BODY1]], ^[[BODY2:.*]]
|
||||
! CHECK: scf.while : () -> () {
|
||||
! 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: cf.cond_br %[[COND2]], ^[[BODY2]], ^[[EXIT2:.*]]
|
||||
! CHECK: scf.condition(%[[COND2]])
|
||||
! CHECK: } do {
|
||||
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: cf.br ^[[HDR2]]
|
||||
! CHECK: scf.yield
|
||||
end do
|
||||
! CHECK: }
|
||||
|
||||
! CHECK: ^[[EXIT2]]: // pred: ^[[HDR2]]
|
||||
! CHECK: cf.br ^[[HDR1]]
|
||||
! CHECK: scf.yield
|
||||
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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user