diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 5d5ac0f274773..66ee2f6ecaea4 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -111,7 +111,6 @@ struct IncrementLoopInfo { llvm::SmallVector localInitSymList; llvm::SmallVector sharedSymList; mlir::Value loopVariable = nullptr; - mlir::Value stepValue = nullptr; // possible uses in multiple blocks // Data members for structured loops. fir::DoLoopOp doLoop = nullptr; @@ -119,6 +118,7 @@ struct IncrementLoopInfo { // Data members for unstructured loops. bool hasRealControl = false; mlir::Value tripVariable = nullptr; + mlir::Value stepVariable = nullptr; mlir::Block *headerBlock = nullptr; // loop entry and test block mlir::Block *maskBlock = nullptr; // concurrent loop mask block mlir::Block *bodyBlock = nullptr; // first loop body block @@ -1708,29 +1708,45 @@ class FirConverter : public Fortran::lower::AbstractConverter { genFIR(endDoEval, unstructuredContext); } + /// Generate FIR to evaluate loop control values (lower, upper and step). + mlir::Value genControlValue(const Fortran::lower::SomeExpr *expr, + const IncrementLoopInfo &info, + bool *isConst = nullptr) { + mlir::Location loc = toLocation(); + mlir::Type controlType = info.isStructured() ? builder->getIndexType() + : info.getLoopVariableType(); + Fortran::lower::StatementContext stmtCtx; + if (expr) { + if (isConst) + *isConst = Fortran::evaluate::IsConstantExpr(*expr); + return builder->createConvert(loc, controlType, + createFIRExpr(loc, expr, stmtCtx)); + } + + if (isConst) + *isConst = true; + if (info.hasRealControl) + return builder->createRealConstant(loc, controlType, 1u); + return builder->createIntegerConstant(loc, controlType, 1); // step + } + /// Generate FIR to begin a structured or unstructured increment loop nest. void genFIRIncrementLoopBegin(IncrementLoopNestInfo &incrementLoopNestInfo) { assert(!incrementLoopNestInfo.empty() && "empty loop nest"); mlir::Location loc = toLocation(); - auto genControlValue = [&](const Fortran::lower::SomeExpr *expr, - const IncrementLoopInfo &info) { - mlir::Type controlType = info.isStructured() ? builder->getIndexType() - : info.getLoopVariableType(); - Fortran::lower::StatementContext stmtCtx; - if (expr) - return builder->createConvert(loc, controlType, - createFIRExpr(loc, expr, stmtCtx)); - - if (info.hasRealControl) - return builder->createRealConstant(loc, controlType, 1u); - return builder->createIntegerConstant(loc, controlType, 1); // step - }; for (IncrementLoopInfo &info : incrementLoopNestInfo) { info.loopVariable = genLoopVariableAddress(loc, info.loopVariableSym, info.isUnordered); mlir::Value lowerValue = genControlValue(info.lowerExpr, info); mlir::Value upperValue = genControlValue(info.upperExpr, info); - info.stepValue = genControlValue(info.stepExpr, info); + bool isConst = true; + mlir::Value stepValue = genControlValue( + info.stepExpr, info, info.isStructured() ? nullptr : &isConst); + // Use a temp variable for unstructured loops with non-const step. + if (!isConst) { + info.stepVariable = builder->createTemporary(loc, stepValue.getType()); + builder->create(loc, stepValue, info.stepVariable); + } // Structured loop - generate fir.do_loop. if (info.isStructured()) { @@ -1739,14 +1755,14 @@ class FirConverter : public Fortran::lower::AbstractConverter { if (info.isUnordered) { // The loop variable value is explicitly updated. info.doLoop = builder->create( - loc, lowerValue, upperValue, info.stepValue, /*unordered=*/true); + loc, lowerValue, upperValue, stepValue, /*unordered=*/true); builder->setInsertionPointToStart(info.doLoop.getBody()); loopValue = builder->createConvert(loc, loopVarType, info.doLoop.getInductionVar()); } else { // The loop variable is a doLoop op argument. info.doLoop = builder->create( - loc, lowerValue, upperValue, info.stepValue, /*unordered=*/false, + loc, lowerValue, upperValue, stepValue, /*unordered=*/false, /*finalCountValue=*/true, builder->createConvert(loc, loopVarType, lowerValue)); builder->setInsertionPointToStart(info.doLoop.getBody()); @@ -1775,18 +1791,17 @@ class FirConverter : public Fortran::lower::AbstractConverter { auto diff1 = builder->create(loc, upperValue, lowerValue); auto diff2 = - builder->create(loc, diff1, info.stepValue); - tripCount = - builder->create(loc, diff2, info.stepValue); + builder->create(loc, diff1, stepValue); + tripCount = builder->create(loc, diff2, stepValue); tripCount = builder->createConvert(loc, builder->getIndexType(), tripCount); } else { auto diff1 = builder->create(loc, upperValue, lowerValue); auto diff2 = - builder->create(loc, diff1, info.stepValue); + builder->create(loc, diff1, stepValue); tripCount = - builder->create(loc, diff2, info.stepValue); + builder->create(loc, diff2, stepValue); } if (forceLoopToExecuteOnce) { // minimum tripCount is 1 mlir::Value one = @@ -1874,12 +1889,15 @@ class FirConverter : public Fortran::lower::AbstractConverter { tripCount = builder->create(loc, tripCount, one); builder->create(loc, tripCount, info.tripVariable); mlir::Value value = builder->create(loc, info.loopVariable); + mlir::Value step; + if (info.stepVariable) + step = builder->create(loc, info.stepVariable); + else + step = genControlValue(info.stepExpr, info); if (info.hasRealControl) - value = - builder->create(loc, value, info.stepValue); + value = builder->create(loc, value, step); else - value = - builder->create(loc, value, info.stepValue); + value = builder->create(loc, value, step); builder->create(loc, value, info.loopVariable); genBranch(info.headerBlock); diff --git a/flang/test/Lower/HLFIR/goto-do-body.f90 b/flang/test/Lower/HLFIR/goto-do-body.f90 new file mode 100644 index 0000000000000..383b839e591e3 --- /dev/null +++ b/flang/test/Lower/HLFIR/goto-do-body.f90 @@ -0,0 +1,114 @@ +! RUN: bbc --hlfir -o - %s | FileCheck %s + +! Test jumping to the body of a do loop. +subroutine sub1() +! CHECK-LABEL: func @_QPsub1() { + implicit none + integer :: i + external foo +! CHECK: %[[C2:.*]] = arith.constant 2 : i32 +! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK: %[[C1:.*]] = arith.constant 1 : i32 +! CHECK: %[[TRIP:.*]] = fir.alloca i32 +! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", {{.*}}} +! CHECK: %[[I:.*]]:2 = hlfir.declare %[[I_REF]] {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) + + do i = 1, 3 + if (i .eq. 2) goto 70 +! CHECK: %[[TMP1:.*]] = fir.load %[[I]]#0 : !fir.ref +! CHECK: %[[COND:.*]] = arith.cmpi eq, %[[TMP1]], %[[C2]] : i32 +! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^{{.*}} + + end do + + call foo +! CHECK: fir.call @_QPfoo() + + do i = 1, 2 +! CHECK: fir.store %[[C2]] to %[[TRIP]] : !fir.ref +! CHECK: fir.store %[[C1]] to %[[I]]#1 : !fir.ref +! CHECK: cf.br ^[[HEADER:.*]] +! CHECK: ^[[HEADER]]: +! CHECK: %[[TMP2:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[TMP3:.*]] = arith.cmpi sgt, %[[TMP2]], %[[C0]] : i32 +! CHECK: cf.cond_br %[[TMP3]], ^[[BODY]], ^[[EXIT:.*]] + + 70 call foo +! CHECK: ^[[BODY]]: +! CHECK: fir.call @_QPfoo() +! CHECK: %[[TMP4:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[TMP5:.*]] = arith.subi %[[TMP4]], %[[C1]] : i32 +! CHECK: fir.store %[[TMP5]] to %[[TRIP]] : !fir.ref +! CHECK: %[[TMP6:.*]] = fir.load %[[I]]#1 : !fir.ref +! CHECK: %[[TMP7:.*]] = arith.addi %[[TMP6]], %[[C1]] : i32 +! CHECK: fir.store %[[TMP7]] to %[[I]]#1 : !fir.ref +! CHECK: cf.br ^[[HEADER]] + end do +end subroutine +! CHECK: ^[[EXIT]]: +! CHECK: return +! CHECK: } + +! Test jumping to the body of a do loop with a step expression. +subroutine sub2() +! CHECK-LABEL: func @_QPsub2() { + implicit none + integer :: i, j + external foo +! CHECK: %[[C_7:.*]] = arith.constant -7 : i32 +! CHECK: %[[C8:.*]] = arith.constant 8 : i32 +! CHECK: %[[C2:.*]] = arith.constant 2 : i32 +! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK: %[[C3:.*]] = arith.constant 3 : i32 +! CHECK: %[[C1:.*]] = arith.constant 1 : i32 +! CHECK: %[[TRIP:.*]] = fir.alloca i32 +! CHECK: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", {{.*}}} +! CHECK: %[[I:.*]]:2 = hlfir.declare %[[I_REF]] {uniq_name = "_QFsub2Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[J_REF:.*]] = fir.alloca i32 {bindc_name = "j", {{.*}}} +! CHECK: %[[J:.*]]:2 = hlfir.declare %[[J_REF]] {uniq_name = "_QFsub2Ej"} : (!fir.ref) -> (!fir.ref, !fir.ref) + + do i = 1, 3 + if (i .eq. 2) goto 70 +! CHECK: %[[TMP1:.*]] = fir.load %[[I]]#0 : !fir.ref +! CHECK: %[[COND:.*]] = arith.cmpi eq, %[[TMP1]], %[[C2]] : i32 +! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^{{.*}} + + end do + + call foo +! CHECK: fir.call @_QPfoo() + + j = 3 +! CHECK: hlfir.assign %[[C3]] to %[[J]]#0 : i32, !fir.ref + + do i = 1, 2, 3 * j - 8 +! CHECK: %[[TMP2:.*]] = fir.load %[[J]]#0 : !fir.ref +! CHECK: %[[TMP3:.*]] = arith.muli %[[TMP2]], %[[C3]] : i32 +! CHECK: %[[STEP:.*]] = arith.subi %[[TMP3]], %[[C8]] : i32 +! CHECK: fir.store %[[STEP]] to %[[STEP_VAR:.*]] : !fir.ref +! CHECK: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[C_7]] : i32 +! CHECK: %[[TMP5:.*]] = arith.divsi %[[TMP4]], %[[STEP]] : i32 +! CHECK: fir.store %[[TMP5]] to %[[TRIP]] : !fir.ref +! CHECK: fir.store %[[C1]] to %[[I]]#1 : !fir.ref +! CHECK: cf.br ^[[HEADER:.*]] +! CHECK: ^[[HEADER]]: +! CHECK: %[[TMP6:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[TMP7:.*]] = arith.cmpi sgt, %[[TMP6]], %[[C0]] : i32 +! CHECK: cf.cond_br %[[TMP7]], ^[[BODY]], ^[[EXIT:.*]] + + 70 call foo +! CHECK: ^[[BODY]]: +! CHECK: fir.call @_QPfoo() +! CHECK: %[[TMP8:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[TMP9:.*]] = arith.subi %[[TMP8]], %[[C1]] : i32 +! CHECK: fir.store %[[TMP9]] to %[[TRIP]] : !fir.ref +! CHECK: %[[TMP10:.*]] = fir.load %[[I]]#1 : !fir.ref +! CHECK: %[[STEP_VAL:.*]] = fir.load %[[STEP_VAR]] : !fir.ref +! CHECK: %[[TMP11:.*]] = arith.addi %[[TMP10]], %[[STEP_VAL]] : i32 +! CHECK: fir.store %[[TMP11]] to %[[I]]#1 : !fir.ref +! CHECK: cf.br ^[[HEADER]] + end do +end subroutine +! CHECK: ^[[EXIT]]: +! CHECK: return +! CHECK: } diff --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90 index 512168763ceb9..d6ca1fe70977d 100644 --- a/flang/test/Lower/do_loop.f90 +++ b/flang/test/Lower/do_loop.f90 @@ -245,6 +245,7 @@ subroutine loop_with_real_control(s,e,st) ! CHECK-DAG: %[[S:.*]] = fir.load %[[S_REF]] : !fir.ref ! CHECK-DAG: %[[E:.*]] = fir.load %[[E_REF]] : !fir.ref ! CHECK-DAG: %[[ST:.*]] = fir.load %[[ST_REF]] : !fir.ref + ! CHECK: fir.store %[[ST]] to %[[ST_VAR:.*]] : !fir.ref real :: x, s, e, st ! CHECK: %[[DIFF:.*]] = arith.subf %[[E]], %[[S]] {{.*}}: f32 @@ -267,7 +268,8 @@ subroutine loop_with_real_control(s,e,st) ! CHECK: %[[INC:.*]] = arith.subi %[[INDEX2]], %[[C1]] : index ! CHECK: fir.store %[[INC]] to %[[INDEX_REF]] : !fir.ref ! CHECK: %[[X2:.*]] = fir.load %[[X_REF]] : !fir.ref - ! CHECK: %[[XINC:.*]] = arith.addf %[[X2]], %[[ST]] {{.*}}: f32 + ! CHECK: %[[ST_VAL:.*]] = fir.load %[[ST_VAR]] : !fir.ref + ! CHECK: %[[XINC:.*]] = arith.addf %[[X2]], %[[ST_VAL]] {{.*}}: f32 ! CHECK: fir.store %[[XINC]] to %[[X_REF]] : !fir.ref ! CHECK: br ^[[HDR]] end do diff --git a/flang/test/Lower/do_loop_unstructured.f90 b/flang/test/Lower/do_loop_unstructured.f90 index a8c849a488279..2b5f1c6c0061a 100644 --- a/flang/test/Lower/do_loop_unstructured.f90 +++ b/flang/test/Lower/do_loop_unstructured.f90 @@ -37,7 +37,8 @@ subroutine simple_unstructured() ! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32 ! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref ! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref -! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_ONE]] : i32 +! CHECK: %[[STEP_ONE_2:.*]] = arith.constant 1 : i32 +! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_ONE_2]] : i32 ! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref ! CHECK: cf.br ^[[HEADER]] ! CHECK: ^[[EXIT]]: @@ -75,7 +76,8 @@ subroutine simple_unstructured_with_step() ! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32 ! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref ! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref -! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP]] : i32 +! CHECK: %[[STEP_2:.*]] = arith.constant 2 : i32 +! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_2]] : i32 ! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref ! CHECK: cf.br ^[[HEADER]] ! CHECK: ^[[EXIT]]: @@ -151,7 +153,8 @@ subroutine nested_unstructured() ! CHECK: %[[TRIP_VAR_K_NEXT:.*]] = arith.subi %[[TRIP_VAR_K]], %[[ONE_1]] : i32 ! CHECK: fir.store %[[TRIP_VAR_K_NEXT]] to %[[TRIP_VAR_K_REF]] : !fir.ref ! CHECK: %[[LOOP_VAR_K:.*]] = fir.load %[[LOOP_VAR_K_REF]] : !fir.ref -! CHECK: %[[LOOP_VAR_K_NEXT:.*]] = arith.addi %[[LOOP_VAR_K]], %[[K_STEP]] : i32 +! CHECK: %[[K_STEP_2:.*]] = arith.constant 1 : i32 +! CHECK: %[[LOOP_VAR_K_NEXT:.*]] = arith.addi %[[LOOP_VAR_K]], %[[K_STEP_2]] : i32 ! CHECK: fir.store %[[LOOP_VAR_K_NEXT]] to %[[LOOP_VAR_K_REF]] : !fir.ref ! CHECK: cf.br ^[[HEADER_K]] ! CHECK: ^[[EXIT_K]]: @@ -160,7 +163,8 @@ subroutine nested_unstructured() ! CHECK: %[[TRIP_VAR_J_NEXT:.*]] = arith.subi %[[TRIP_VAR_J]], %[[ONE_1]] : i32 ! CHECK: fir.store %[[TRIP_VAR_J_NEXT]] to %[[TRIP_VAR_J_REF]] : !fir.ref ! CHECK: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref -! CHECK: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %[[J_STEP]] : i32 +! CHECK: %[[J_STEP_2:.*]] = arith.constant 1 : i32 +! CHECK: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %[[J_STEP_2]] : i32 ! CHECK: fir.store %[[LOOP_VAR_J_NEXT]] to %[[LOOP_VAR_J_REF]] : !fir.ref ! CHECK: cf.br ^[[HEADER_J]] ! CHECK: ^[[EXIT_J]]: @@ -169,7 +173,8 @@ subroutine nested_unstructured() ! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[ONE_1]] : i32 ! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref ! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref -! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP]] : i32 +! CHECK: %[[I_STEP_2:.*]] = arith.constant 1 : i32 +! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] : i32 ! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref ! CHECK: cf.br ^[[HEADER_I]] ! CHECK: ^[[EXIT_I]]: @@ -215,7 +220,8 @@ subroutine nested_structured_in_unstructured() ! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[C1_3]] : i32 ! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref ! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref -! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %c1_i32_0 : i32 +! CHECK: %[[I_STEP_2:.*]] = arith.constant 1 : i32 +! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] : i32 ! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref ! CHECK: cf.br ^[[HEADER]] ! CHECK: ^[[EXIT]]: diff --git a/flang/test/Lower/goto-do-body.f90 b/flang/test/Lower/goto-do-body.f90 new file mode 100644 index 0000000000000..3854947b55f62 --- /dev/null +++ b/flang/test/Lower/goto-do-body.f90 @@ -0,0 +1,125 @@ +! RUN: bbc %s -emit-fir -o - | FileCheck %s + +! Test jumping to the body of a do loop. +subroutine sub1() +! CHECK-LABEL: func @_QPsub1() { + implicit none + integer :: i + external foo +! CHECK: %[[TRIP:.*]] = fir.alloca i32 +! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", {{.*}}} + + do i = 1, 3 + if (i .eq. 2) goto 70 +! CHECK: %[[TMP1:.*]] = fir.load %[[I]] : !fir.ref +! CHECK: %[[C2_1:.*]] = arith.constant 2 : i32 +! CHECK: %[[COND:.*]] = arith.cmpi eq, %[[TMP1]], %[[C2_1]] : i32 +! CHECK: cf.cond_br %[[COND]], ^[[COND_TRUE:.*]], ^{{.*}} +! CHECK: ^[[COND_TRUE]]: +! CHECK: cf.br ^[[BODY:.*]] + + end do + + call foo +! CHECK: fir.call @_QPfoo() + + do i = 1, 2 +! CHECK: %[[C1_1:.*]] = arith.constant 1 : i32 +! CHECK: %[[C2_2:.*]] = arith.constant 2 : i32 +! CHECK: %[[C1_2:.*]] = arith.constant 1 : i32 +! CHECK: %[[TMP2:.*]] = arith.subi %[[C2_2]], %[[C1_1]] : i32 +! CHECK: %[[TMP3:.*]] = arith.addi %[[TMP2]], %[[C1_2]] : i32 +! CHECK: %[[TMP4:.*]] = arith.divsi %[[TMP3]], %[[C1_2]] : i32 +! CHECK: fir.store %[[TMP4]] to %[[TRIP]] : !fir.ref +! CHECK: fir.store %[[C1_1]] to %[[I]] : !fir.ref +! CHECK: cf.br ^[[HEADER:.*]] +! CHECK: ^[[HEADER]]: +! CHECK: %[[TMP5:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[TMP6:.*]] = arith.cmpi sgt, %[[TMP5]], %[[C0_1]] : i32 +! CHECK: cf.cond_br %[[TMP6]], ^[[BODY]], ^[[EXIT:.*]] + + 70 call foo +! CHECK: ^[[BODY]]: +! CHECK: fir.call @_QPfoo() +! CHECK: %[[TMP7:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[C1_3:.*]] = arith.constant 1 : i32 +! CHECK: %[[TMP8:.*]] = arith.subi %[[TMP7]], %[[C1_3]] : i32 +! CHECK: fir.store %[[TMP8]] to %[[TRIP]] : !fir.ref +! CHECK: %[[TMP9:.*]] = fir.load %[[I]] : !fir.ref +! CHECK: %[[C1_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[TMP10:.*]] = arith.addi %[[TMP9]], %[[C1_4]] : i32 +! CHECK: fir.store %[[TMP10]] to %[[I]] : !fir.ref +! CHECK: cf.br ^[[HEADER]] + end do +end subroutine +! CHECK: ^[[EXIT]]: +! CHECK: return +! CHECK: } + +! Test jumping to the body of a do loop with a step expression. +subroutine sub2() +! CHECK-LABEL: func @_QPsub2() { + implicit none + integer :: i, j + external foo +! CHECK: %[[TRIP:.*]] = fir.alloca i32 +! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", {{.*}}} +! CHECK: %[[J:.*]] = fir.alloca i32 {bindc_name = "j", {{.*}}} + + do i = 1, 3 + if (i .eq. 2) goto 70 +! CHECK: %[[TMP1:.*]] = fir.load %[[I]] : !fir.ref +! CHECK: %[[C2_1:.*]] = arith.constant 2 : i32 +! CHECK: %[[COND:.*]] = arith.cmpi eq, %[[TMP1]], %[[C2_1]] : i32 +! CHECK: cf.cond_br %[[COND]], ^[[COND_TRUE:.*]], ^{{.*}} +! CHECK: ^[[COND_TRUE]]: +! CHECK: cf.br ^[[BODY:.*]] + + end do + + call foo +! CHECK: fir.call @_QPfoo() + + j = 3 +! CHECK: %[[C3_1:.*]] = arith.constant 3 : i32 +! CHECK: fir.store %[[C3_1]] to %[[J]] : !fir.ref + + do i = 1, 2, 3 * j - 8 +! CHECK: %[[C1_1:.*]] = arith.constant 1 : i32 +! CHECK: %[[C2_2:.*]] = arith.constant 2 : i32 +! CHECK: %[[C3_2:.*]] = arith.constant 3 : i32 +! CHECK: %[[TMP2:.*]] = fir.load %[[J]] : !fir.ref +! CHECK: %[[TMP3:.*]] = arith.muli %[[C3_2]], %[[TMP2]] : i32 +! CHECK: %[[C8_1:.*]] = arith.constant 8 : i32 +! CHECK: %[[STEP:.*]] = arith.subi %[[TMP3]], %[[C8_1]] : i32 +! CHECK: fir.store %[[STEP]] to %[[STEP_VAR:.*]] : !fir.ref +! CHECK: %[[TMP4:.*]] = arith.subi %[[C2_2]], %[[C1_1]] : i32 +! CHECK: %[[TMP5:.*]] = arith.addi %[[TMP4]], %[[STEP]] : i32 +! CHECK: %[[TMP6:.*]] = arith.divsi %[[TMP5]], %[[STEP]] : i32 +! CHECK: fir.store %[[TMP6]] to %[[TRIP]] : !fir.ref +! CHECK: fir.store %[[C1_1]] to %[[I]] : !fir.ref +! CHECK: cf.br ^[[HEADER:.*]] +! CHECK: ^[[HEADER]]: +! CHECK: %[[TMP7:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[TMP8:.*]] = arith.cmpi sgt, %[[TMP7]], %[[C0_1]] : i32 +! CHECK: cf.cond_br %[[TMP8]], ^[[BODY]], ^[[EXIT:.*]] + + 70 call foo +! CHECK: ^[[BODY]]: +! CHECK: fir.call @_QPfoo() +! CHECK: %[[TMP9:.*]] = fir.load %[[TRIP]] : !fir.ref +! CHECK: %[[C1_2:.*]] = arith.constant 1 : i32 +! CHECK: %[[TMP10:.*]] = arith.subi %[[TMP9]], %[[C1_2]] : i32 +! CHECK: fir.store %[[TMP10]] to %[[TRIP]] : !fir.ref +! CHECK: %[[TMP11:.*]] = fir.load %[[I]] : !fir.ref +! CHECK: %[[STEP_VAL:.*]] = fir.load %[[STEP_VAR]] : !fir.ref +! CHECK: %[[TMP12:.*]] = arith.addi %[[TMP11]], %[[STEP_VAL]] : i32 +! CHECK: fir.store %[[TMP12]] to %[[I]] : !fir.ref +! CHECK: cf.br ^[[HEADER]] + end do +end subroutine +! CHECK: ^[[EXIT]]: +! CHECK: return +! CHECK: } diff --git a/flang/test/Lower/loops2.f90 b/flang/test/Lower/loops2.f90 index 78795fa642ea4..4baf4f2b6ec38 100644 --- a/flang/test/Lower/loops2.f90 +++ b/flang/test/Lower/loops2.f90 @@ -52,8 +52,9 @@ subroutine test_real_pointer() ! CHECK: cond_br %{{.*}}, ^bb2, ^bb3 ! CHECK: ^bb2: ! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_3]] : !fir.ptr -! CHECK: %[[VAL_20:.*]] = arith.addf %[[VAL_19]], %[[VAL_8]] {{.*}}: f32 -! CHECK: fir.store %[[VAL_20]] to %[[VAL_3]] : !fir.ptr +! CHECK: %[[VAL_20:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_21:.*]] = arith.addf %[[VAL_19]], %[[VAL_20]] {{.*}}: f32 +! CHECK: fir.store %[[VAL_21]] to %[[VAL_3]] : !fir.ptr ! CHECK: br ^bb1 ! CHECK: ^bb3: ! CHECK: return @@ -77,8 +78,9 @@ subroutine test_real_allocatable() ! CHECK: cond_br %{{.*}}, ^bb2, ^bb3 ! CHECK: ^bb2: ! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_3]] : !fir.heap -! CHECK: %[[VAL_20:.*]] = arith.addf %[[VAL_19]], %[[VAL_8]] {{.*}}: f32 -! CHECK: fir.store %[[VAL_20]] to %[[VAL_3]] : !fir.heap +! CHECK: %[[VAL_20:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[VAL_21:.*]] = arith.addf %[[VAL_19]], %[[VAL_20]] {{.*}}: f32 +! CHECK: fir.store %[[VAL_21]] to %[[VAL_3]] : !fir.heap ! CHECK: br ^bb1 ! CHECK: ^bb3: ! CHECK: return @@ -103,8 +105,9 @@ subroutine test_pointer_unstructured_loop() ! CHECK: ^bb3: ! CHECK: br ^bb5 ! CHECK: ^bb4: -! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_3]] : !fir.ptr -! CHECK: %[[VAL_22:.*]] = arith.addi %[[VAL_21]], %[[VAL_6]] : i32 +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_3]] : !fir.ptr +! CHECK: %[[VAL_21:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_22:.*]] = arith.addi %[[VAL_20]], %[[VAL_21]] : i32 ! CHECK: fir.store %[[VAL_22]] to %[[VAL_3]] : !fir.ptr ! CHECK: br ^bb1 ! CHECK: ^bb5: diff --git a/flang/test/Lower/mixed_loops.f90 b/flang/test/Lower/mixed_loops.f90 index 651919dd5b3b1..dcbc789398345 100644 --- a/flang/test/Lower/mixed_loops.f90 +++ b/flang/test/Lower/mixed_loops.f90 @@ -52,7 +52,8 @@ subroutine while_inside_do_loop ! CHECK: %[[TDEC:.*]] = arith.subi %[[T2]], %[[C1_AGAIN]] : i32 ! CHECK: fir.store %[[TDEC]] to %[[T_REF]] ! CHECK: %[[I3:.*]] = fir.load %[[I_REF]] : !fir.ref - ! CHECK: %[[IINC:.*]] = arith.addi %[[I3]], %[[C1]] : i32 + ! CHECK: %[[C1_2:.*]] = arith.constant 1 : i32 + ! CHECK: %[[IINC:.*]] = arith.addi %[[I3]], %[[C1_2]] : i32 ! CHECK: fir.store %[[IINC]] to %[[I_REF]] : !fir.ref ! CHECK: br ^[[HDR1]] end do