[flang-commits] [flang] 8c349d7 - [Flang] Lower the infinite do loop
Kiran Chandramohan via flang-commits
flang-commits at lists.llvm.org
Wed Jun 1 05:07:15 PDT 2022
Author: Kiran Chandramohan
Date: 2022-06-01T12:06:40Z
New Revision: 8c349d707ec2677e6235b4e9e3efa1e0c4de11f2
URL: https://github.com/llvm/llvm-project/commit/8c349d707ec2677e6235b4e9e3efa1e0c4de11f2
DIFF: https://github.com/llvm/llvm-project/commit/8c349d707ec2677e6235b4e9e3efa1e0c4de11f2.diff
LOG: [Flang] Lower the infinite do loop
The basic infinite loop is lowered to a branch to the body of the
loop, and the body containing a back edge as its terminator.
Note: This is part of upstreaming from the fir-dev branch of
https://github.com/flang-compiler/f18-llvm-project.
Reviewed By: rovka
Differential Revision: https://reviews.llvm.org/D126697
Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>
Co-authored-by: V Donaldson <vdonaldson at nvidia.com>
Added:
flang/test/Lower/infinite_loop.f90
Modified:
flang/lib/Lower/Bridge.cpp
Removed:
################################################################################
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index bbce38eb3ad8..a1100ac0afe3 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -983,8 +983,13 @@ class FirConverter : public Fortran::lower::AbstractConverter {
mlir::Block *exitBlock = doStmtEval.parentConstruct->constructExit->block;
IncrementLoopNestInfo incrementLoopNestInfo;
const Fortran::parser::ScalarLogicalExpr *whileCondition = nullptr;
- if ((whileCondition = std::get_if<Fortran::parser::ScalarLogicalExpr>(
- &loopControl->u))) {
+ bool infiniteLoop = !loopControl.has_value();
+ if (infiniteLoop) {
+ assert(unstructuredContext && "infinite loop must be unstructured");
+ startBlock(headerBlock);
+ } else if ((whileCondition =
+ std::get_if<Fortran::parser::ScalarLogicalExpr>(
+ &loopControl->u))) {
assert(unstructuredContext && "while loop must be unstructured");
maybeStartBlock(preheaderBlock); // no block or empty block
startBlock(headerBlock);
@@ -1008,9 +1013,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
TODO(toLocation(), "infinite/unstructured loop/concurrent loop");
}
- // Increment loop begin code. (TODO: Infinite/while code was already
- // generated.)
- if (!whileCondition)
+ // Increment loop begin code. (Infinite/while code was already generated.)
+ if (!infiniteLoop && !whileCondition)
genFIRIncrementLoopBegin(incrementLoopNestInfo);
// Loop body code - NonLabelDoStmt and EndDoStmt code is generated here.
@@ -1018,8 +1022,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
for (Fortran::lower::pft::Evaluation &e : eval.getNestedEvaluations())
genFIR(e, unstructuredContext);
- // Loop end code. (TODO: infinite loop)
- if (whileCondition)
+ // Loop end code.
+ if (infiniteLoop || whileCondition)
genFIRBranch(headerBlock);
else
genFIRIncrementLoopEnd(incrementLoopNestInfo);
diff --git a/flang/test/Lower/infinite_loop.f90 b/flang/test/Lower/infinite_loop.f90
new file mode 100644
index 000000000000..8c36ac105c46
--- /dev/null
+++ b/flang/test/Lower/infinite_loop.f90
@@ -0,0 +1,126 @@
+! RUN: bbc -emit-fir -o - %s | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -o - %s | FileCheck %s
+
+! Tests for infinite loop.
+
+subroutine empty_infinite()
+ do
+ end do
+end subroutine
+! CHECK-LABEL: empty_infinite
+! CHECK: cf.br ^[[BODY:.*]]
+! CHECK: ^[[BODY]]:
+! CHECK: cf.br ^[[BODY]]
+
+subroutine simple_infinite(i)
+ integer :: i
+ do
+ if (i .gt. 100) exit
+ end do
+end subroutine
+! CHECK-LABEL: simple_infinite
+! CHECK-SAME: %[[I_REF:.*]]: !fir.ref<i32>
+! CHECK: cf.br ^[[BODY1:.*]]
+! CHECK: ^[[BODY1]]:
+! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32>
+! CHECK: %[[C100:.*]] = arith.constant 100 : i32
+! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[I]], %[[C100]] : i32
+! CHECK: cf.cond_br %[[COND]], ^[[EXIT:.*]], ^[[BODY1:.*]]
+! CHECK: ^[[EXIT]]:
+! CHECK: cf.br ^[[RETURN:.*]]
+! CHECK: ^[[RETURN]]:
+! CHECK: return
+! CHECK: }
+
+subroutine infinite_with_two_body_blocks(i)
+ integer :: i
+ do
+ i = i + 1
+ if (i .gt. 100) exit
+ i = i * 2
+ end do
+end subroutine
+! CHECK-LABEL: infinite_with_two_body_blocks
+! CHECK-SAME: %[[I_REF:.*]]: !fir.ref<i32>
+! CHECK: cf.br ^[[BODY1:.*]]
+! CHECK: ^[[BODY1]]:
+! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32>
+! CHECK: %[[C1:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_NEXT:.*]] = arith.addi %[[I]], %[[C1]] : i32
+! CHECK: fir.store %[[I_NEXT]] to %[[I_REF]] : !fir.ref<i32>
+! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32>
+! CHECK: %[[C100:.*]] = arith.constant 100 : i32
+! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[I]], %[[C100]] : i32
+! CHECK: cf.cond_br %[[COND]], ^[[EXIT:.*]], ^[[BODY2:.*]]
+! CHECK: ^[[EXIT]]:
+! CHECK: cf.br ^[[RETURN:.*]]
+! CHECK: ^[[BODY2]]:
+! CHECK: %[[C2:.*]] = arith.constant 2 : i32
+! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32>
+! CHECK: %[[I_NEXT:.*]] = arith.muli %[[C2]], %[[I]] : i32
+! CHECK: fir.store %[[I_NEXT]] to %[[I_REF]] : !fir.ref<i32>
+! CHECK: cf.br ^[[BODY1]]
+! CHECK: ^[[RETURN]]:
+! CHECK: return
+! CHECK: }
+
+subroutine structured_loop_in_infinite(i)
+ integer :: i
+ integer :: j
+ do
+ if (i .gt. 100) exit
+ do j=1,10
+ end do
+ end do
+end subroutine
+! CHECK-LABEL: structured_loop_in_infinite
+! CHECK-SAME: %[[I_REF:.*]]: !fir.ref<i32>
+! CHECK: %[[J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFstructured_loop_in_infiniteEj"}
+! CHECK: cf.br ^[[BODY1:.*]]
+! CHECK: ^[[BODY1]]:
+! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32>
+! CHECK: %[[C100:.*]] = arith.constant 100 : i32
+! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[I]], %[[C100]] : i32
+! CHECK: cf.cond_br %[[COND]], ^[[EXIT:.*]], ^[[BODY2:.*]]
+! CHECK: ^[[EXIT]]:
+! CHECK: cf.br ^[[RETURN:.*]]
+! CHECK: ^[[BODY2:.*]]:
+! CHECK: %[[C1:.*]] = arith.constant 1 : i32
+! CHECK: %[[C1_INDEX:.*]] = fir.convert %[[C1]] : (i32) -> index
+! CHECK: %[[C10:.*]] = arith.constant 10 : i32
+! CHECK: %[[C10_INDEX:.*]] = fir.convert %[[C10]] : (i32) -> index
+! CHECK: %[[C1_1:.*]] = arith.constant 1 : index
+! CHECK: %[[J_FINAL:.*]] = fir.do_loop %[[J:.*]] = %[[C1_INDEX]] to %[[C10_INDEX]] step %[[C1_1]] -> index {
+! CHECK: %[[J_I32:.*]] = fir.convert %[[J]] : (index) -> i32
+! CHECK: fir.store %[[J_I32]] to %[[J_REF]] : !fir.ref<i32>
+! CHECK: %[[J_NEXT:.*]] = arith.addi %[[J]], %[[C1_1]] : index
+! CHECK: fir.result %[[J_NEXT]] : index
+! CHECK: }
+! CHECK: %[[J_I32:.*]] = fir.convert %[[J_FINAL]] : (index) -> i32
+! CHECK: fir.store %[[J_I32]] to %[[J_REF]] : !fir.ref<i32>
+! CHECK: cf.br ^[[BODY1]]
+! CHECK: ^[[RETURN]]:
+! CHECK: return
+
+subroutine empty_infinite_in_while(i)
+ integer :: i
+ do while (i .gt. 50)
+ do
+ end do
+ end do
+end subroutine
+
+! CHECK-LABEL: empty_infinite_in_while
+! CHECK-SAME: %[[I_REF:.*]]: !fir.ref<i32>
+! CHECK: cf.br ^bb1
+! CHECK: ^bb1:
+! CHECK: %[[I:.*]] = fir.load %[[I_REF]] : !fir.ref<i32>
+! CHECK: %[[C50:.*]] = arith.constant 50 : i32
+! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[I]], %[[C50]] : i32
+! CHECK: cf.cond_br %[[COND]], ^[[INF_HEADER:.*]], ^[[EXIT:.*]]
+! CHECK: ^[[INF_HEADER]]:
+! CHECK: cf.br ^[[INF_BODY:.*]]
+! CHECK: ^[[INF_BODY]]:
+! CHECK: cf.br ^[[INF_HEADER]]
+! CHECK: ^[[EXIT]]:
+! CHECK: return
More information about the flang-commits
mailing list