[flang-commits] [flang] [flang] Lower plain DO loops without a secondary-induction iter_arg (PR #207816)

via flang-commits flang-commits at lists.llvm.org
Mon Jul 20 03:47:03 PDT 2026


https://github.com/khaki3 updated https://github.com/llvm/llvm-project/pull/207816

>From d475f6108697604ce4cd7e48853ffd7eb3bbb3a7 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 29 Jun 2026 14:15:31 -0700
Subject: [PATCH 01/12] [flang] Option to drop iter_arg for do-concurrent
 nested loops

Add the DoConcurrentCleanNestedLoops lowering option. When set, plain DO
loops nested inside a DO CONCURRENT body are lowered without the
secondary-induction iter_arg: the DO variable is recomputed from the
induction variable. This keeps the loop body free of a loop-carried value
that hides memory recurrences (e.g. reductions) from later analyses,
matching how loops in OpenACC regions are lowered.

The post-loop final value of the DO variable is not preserved, so the
option is only valid where those loop variables are effectively private
(the parallel do-concurrent path). Off by default.
---
 flang/include/flang/Lower/LoweringOptions.def |  9 +++++
 flang/lib/Lower/Bridge.cpp                    | 40 +++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def
index 0b02ffd5a3b22..6f3c3ec06fb03 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -93,5 +93,14 @@ ENUM_LOWERINGOPT(PreserveUseDebugInfo, unsigned, 1, 0)
 /// Portable, Extremum, ExtremeNum). Default: Legacy.
 ENUM_LOWERINGOPT(FPMaxminBehavior, Fortran::common::FPMaxminBehavior, 2, 0)
 
+/// If true, lower plain DO loops nested inside a DO CONCURRENT body without the
+/// secondary-induction iter_arg: the DO variable is recomputed from the
+/// induction variable. This keeps the loop body free of a loop-carried value
+/// that would otherwise hide memory recurrences (e.g. reductions) from later
+/// analyses. The post-loop final value of the DO variable is not preserved, so
+/// this is only valid where those loop variables are effectively private (the
+/// parallel do-concurrent path). Off by default.
+ENUM_LOWERINGOPT(DoConcurrentCleanNestedLoops, unsigned, 1, 0)
+
 #undef LOWERINGOPT
 #undef ENUM_LOWERINGOPT
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 3679eea9a0955..2a8126fe05b6e 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2995,6 +2995,18 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     }
   }
 
+  /// Return true if the builder's current insertion point is within a
+  /// `fir.do_concurrent.loop` region (i.e. a plain DO loop being lowered here
+  /// is nested inside a DO CONCURRENT body).
+  bool isInsideDoConcurrentLoop() {
+    mlir::Block *block = builder->getInsertionBlock();
+    if (!block)
+      return false;
+    mlir::Operation *parentOp = block->getParentOp();
+    return parentOp && (mlir::isa<fir::DoConcurrentLoopOp>(parentOp) ||
+                        parentOp->getParentOfType<fir::DoConcurrentLoopOp>());
+  }
+
   /// Generate FIR to begin a structured or unstructured increment loop nest.
   void genFIRIncrementLoopBegin(
       IncrementLoopNestInfo &incrementLoopNestInfo,
@@ -3049,6 +3061,27 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
         // The loop variable is a doLoop op argument.
         mlir::Type loopVarType = info.getLoopVariableType();
+
+        // Plain DO loops nested in a DO CONCURRENT body can be lowered without
+        // the secondary-induction iter_arg: recompute the DO variable from the
+        // induction variable. This keeps the body free of a loop-carried value
+        // that would hide memory recurrences (e.g. reductions) from later
+        // analyses, matching how loops in OpenACC regions are lowered.
+        if (getLoweringOptions().getDoConcurrentCleanNestedLoops() &&
+            isInsideDoConcurrentLoop()) {
+          auto loopOp = fir::DoLoopOp::create(
+              *builder, loc, lowerValue, upperValue, stepValue,
+              /*unordered=*/false, /*finalCountValue=*/false,
+              /*iterArgs=*/mlir::ValueRange{});
+          info.loopOp = loopOp;
+          builder->setInsertionPointToStart(loopOp.getBody());
+          mlir::Value loopValue = builder->createConvert(
+              loc, loopVarType, loopOp.getInductionVar());
+          fir::StoreOp::create(*builder, loc, loopValue, info.loopVariable);
+          addLoopAnnotationAttr(info, dirs);
+          continue;
+        }
+
         auto loopOp = fir::DoLoopOp::create(
             *builder, loc, lowerValue, upperValue, stepValue,
             /*unordered=*/false,
@@ -3203,6 +3236,13 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         // End fir.do_loop.
         // Decrement tripVariable.
         auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp);
+        // A clean iter_arg-free loop (DoConcurrentCleanNestedLoops) has no
+        // loop-carried DO variable to step or write back; its terminator is
+        // already in place.
+        if (doLoopOp.getNumRegionIterArgs() == 0) {
+          builder->setInsertionPointAfter(doLoopOp);
+          continue;
+        }
         builder->setInsertionPointToEnd(doLoopOp.getBody());
         // Step loopVariable to help optimizations such as vectorization.
         // Induction variable elimination will clean up as necessary.

>From df2b55ef67ed92cbe6e7d190091a4c16144345b2 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 29 Jun 2026 14:43:08 -0700
Subject: [PATCH 02/12] [flang][bbc] Add -fdo-concurrent-clean-nested-loops
 flag and test

Expose the DoConcurrentCleanNestedLoops lowering option in bbc and add a
Lower test verifying that a plain DO loop nested in a DO CONCURRENT body
is emitted without the secondary-induction iter_arg when the option is set.
---
 .../do_concurrent_clean_nested_loops.f90      | 31 +++++++++++++++++++
 flang/tools/bbc/bbc.cpp                       |  8 +++++
 2 files changed, 39 insertions(+)
 create mode 100644 flang/test/Lower/do_concurrent_clean_nested_loops.f90

diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
new file mode 100644
index 0000000000000..04f53362b6b41
--- /dev/null
+++ b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
@@ -0,0 +1,31 @@
+! Test that -fdo-concurrent-clean-nested-loops lowers a plain DO loop nested in
+! a DO CONCURRENT body without the secondary-induction iter_arg: the DO variable
+! is recomputed from the induction variable instead.
+
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=CHECK,DEFAULT
+! RUN: bbc -emit-hlfir -fdo-concurrent-clean-nested-loops -o - %s | FileCheck %s --check-prefixes=CHECK,CLEAN
+
+subroutine nested(a, n)
+  implicit none
+  integer :: n, i, j
+  integer :: a(n, n)
+  do concurrent (j=1:n)
+    do i = 1, n
+      a(i, j) = i
+    end do
+  end do
+end subroutine
+
+! CHECK-LABEL: func.func @_QPnested
+! CHECK:   %[[I_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnestedEi"}
+! CHECK:   fir.do_concurrent
+! CHECK:     fir.do_concurrent.loop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
+
+! The nested plain DO loop:
+! DEFAULT:     %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[IV:.*]] = %{{.*}}) -> (i32) {
+! DEFAULT:       fir.store %[[IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
+
+! CLEAN:       fir.do_loop %[[IV:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CLEAN-NOT:     iter_args
+! CLEAN:         %[[IV_CVT:.*]] = fir.convert %[[IV]] : (index) -> i32
+! CLEAN:         fir.store %[[IV_CVT]] to %[[I_DECL]]#0 : !fir.ref<i32>
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index e1017a0005b50..6d2a51c20d97a 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -234,6 +234,13 @@ static llvm::cl::opt<bool> enableCUDAInit("fcuda-init",
                                           llvm::cl::desc("enable CUDA Init"),
                                           llvm::cl::init(false));
 
+static llvm::cl::opt<bool> doConcurrentCleanNestedLoops(
+    "fdo-concurrent-clean-nested-loops",
+    llvm::cl::desc(
+        "lower plain DO loops nested in DO CONCURRENT bodies without "
+        "the secondary-induction iter_arg"),
+    llvm::cl::init(false));
+
 static llvm::cl::opt<bool>
     enableDoConcurrentOffload("fdoconcurrent-offload",
                               llvm::cl::desc("enable do concurrent offload"),
@@ -506,6 +513,7 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
   loweringOptions.setRepackArrays(repackArrays);
   loweringOptions.setRepackArraysWhole(repackArraysWhole);
   loweringOptions.setSkipExternalRttiDefinition(skipExternalRttiDefinition);
+  loweringOptions.setDoConcurrentCleanNestedLoops(doConcurrentCleanNestedLoops);
   if (enableCUDA)
     loweringOptions.setCUDARuntimeCheck(true);
   if (complexRange == "improved" || complexRange == "basic")

>From e16389c926959bdb350be6500146bcc070f68a3f Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Tue, 30 Jun 2026 13:37:46 -0700
Subject: [PATCH 03/12] [flang] Preserve DO variable post-loop value for clean
 nested loops

Materialize the Fortran post-loop value (lb + tripCount*step) after the
iter_arg-free nested loop so uses of the DO variable after the loop stay
correct. The value is computed outside the loop body, so it does not
reintroduce a loop-carried recurrence. Makes the lowering option fully
semantics-preserving; updates the test to cover the post-loop use.
---
 flang/include/flang/Lower/LoweringOptions.def | 10 ++--
 flang/lib/Lower/Bridge.cpp                    | 35 ++++++++++----
 .../do_concurrent_clean_nested_loops.f90      | 47 ++++++++++++-------
 3 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def
index 6f3c3ec06fb03..57a4a1adac239 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -95,11 +95,11 @@ ENUM_LOWERINGOPT(FPMaxminBehavior, Fortran::common::FPMaxminBehavior, 2, 0)
 
 /// If true, lower plain DO loops nested inside a DO CONCURRENT body without the
 /// secondary-induction iter_arg: the DO variable is recomputed from the
-/// induction variable. This keeps the loop body free of a loop-carried value
-/// that would otherwise hide memory recurrences (e.g. reductions) from later
-/// analyses. The post-loop final value of the DO variable is not preserved, so
-/// this is only valid where those loop variables are effectively private (the
-/// parallel do-concurrent path). Off by default.
+/// induction variable in the body. This keeps the loop body free of a
+/// loop-carried value that would otherwise hide memory recurrences (e.g.
+/// reductions) from later analyses. The Fortran post-loop value of the DO
+/// variable is still materialized after the loop, so the lowering is
+/// semantics-preserving. Off by default.
 ENUM_LOWERINGOPT(DoConcurrentCleanNestedLoops, unsigned, 1, 0)
 
 #undef LOWERINGOPT
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 2a8126fe05b6e..e83e0c5e55741 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -3062,11 +3062,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         // The loop variable is a doLoop op argument.
         mlir::Type loopVarType = info.getLoopVariableType();
 
-        // Plain DO loops nested in a DO CONCURRENT body can be lowered without
-        // the secondary-induction iter_arg: recompute the DO variable from the
-        // induction variable. This keeps the body free of a loop-carried value
-        // that would hide memory recurrences (e.g. reductions) from later
-        // analyses, matching how loops in OpenACC regions are lowered.
+        // Lower the loop without the secondary-induction iter_arg so memory
+        // recurrences (e.g. reductions) stay visible to later analyses. The DO
+        // variable is recomputed from the induction variable in the body; its
+        // post-loop value is materialized in genFIRIncrementLoopEnd.
         if (getLoweringOptions().getDoConcurrentCleanNestedLoops() &&
             isInsideDoConcurrentLoop()) {
           auto loopOp = fir::DoLoopOp::create(
@@ -3236,11 +3235,31 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         // End fir.do_loop.
         // Decrement tripVariable.
         auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp);
-        // A clean iter_arg-free loop (DoConcurrentCleanNestedLoops) has no
-        // loop-carried DO variable to step or write back; its terminator is
-        // already in place.
+        // Iter_arg-free loop (DoConcurrentCleanNestedLoops): nothing to step in
+        // the body. Materialize the Fortran post-loop value lb + tripCount*step
+        // after the loop so later uses of the DO variable stay correct.
         if (doLoopOp.getNumRegionIterArgs() == 0) {
           builder->setInsertionPointAfter(doLoopOp);
+          mlir::Type type = info.getLoopVariableType();
+          mlir::Value lb =
+              builder->createConvert(loc, type, doLoopOp.getLowerBound());
+          mlir::Value ub =
+              builder->createConvert(loc, type, doLoopOp.getUpperBound());
+          mlir::Value st =
+              builder->createConvert(loc, type, doLoopOp.getStep());
+          mlir::Value zero = builder->createIntegerConstant(loc, type, 0);
+          mlir::Value trip =
+              mlir::arith::SubIOp::create(*builder, loc, ub, lb, iofAttr);
+          trip = mlir::arith::AddIOp::create(*builder, loc, trip, st, iofAttr);
+          trip = mlir::arith::DivSIOp::create(*builder, loc, trip, st);
+          mlir::Value empty = mlir::arith::CmpIOp::create(
+              *builder, loc, mlir::arith::CmpIPredicate::slt, trip, zero);
+          trip =
+              mlir::arith::SelectOp::create(*builder, loc, empty, zero, trip);
+          mlir::Value last =
+              mlir::arith::MulIOp::create(*builder, loc, trip, st, iofAttr);
+          last = mlir::arith::AddIOp::create(*builder, loc, lb, last, iofAttr);
+          fir::StoreOp::create(*builder, loc, last, info.loopVariable);
           continue;
         }
         builder->setInsertionPointToEnd(doLoopOp.getBody());
diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
index 04f53362b6b41..6dfe9a58992c7 100644
--- a/flang/test/Lower/do_concurrent_clean_nested_loops.f90
+++ b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
@@ -1,6 +1,7 @@
-! Test that -fdo-concurrent-clean-nested-loops lowers a plain DO loop nested in
-! a DO CONCURRENT body without the secondary-induction iter_arg: the DO variable
-! is recomputed from the induction variable instead.
+! Test -fdo-concurrent-clean-nested-loops: a plain DO loop nested in a DO
+! CONCURRENT body is lowered without the secondary-induction iter_arg (the DO
+! variable is recomputed from the induction variable), while the Fortran
+! post-loop value of the DO variable is still materialized after the loop.
 
 ! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=CHECK,DEFAULT
 ! RUN: bbc -emit-hlfir -fdo-concurrent-clean-nested-loops -o - %s | FileCheck %s --check-prefixes=CHECK,CLEAN
@@ -8,24 +9,34 @@
 subroutine nested(a, n)
   implicit none
   integer :: n, i, j
-  integer :: a(n, n)
-  do concurrent (j=1:n)
-    do i = 1, n
-      a(i, j) = i
+  integer :: a(n)
+  do concurrent (i=1:n)
+    do j = 1, 3
     end do
+    a(i) = j
   end do
 end subroutine
 
-! CHECK-LABEL: func.func @_QPnested
-! CHECK:   %[[I_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnestedEi"}
-! CHECK:   fir.do_concurrent
-! CHECK:     fir.do_concurrent.loop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
+! CHECK-LABEL:   func.func @_QPnested
+! CHECK:           %[[J_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnestedEj"}
+! CHECK:           fir.do_concurrent
+! CHECK:             fir.do_concurrent.loop
 
-! The nested plain DO loop:
-! DEFAULT:     %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[IV:.*]] = %{{.*}}) -> (i32) {
-! DEFAULT:       fir.store %[[IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
+! Default lowering: nested loop carries the DO variable as an iter_arg and the
+! post-loop value is the loop result.
+! DEFAULT:           %[[RES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! DEFAULT:           fir.store %[[RES]] to %[[J_DECL]]#0 : !fir.ref<i32>
 
-! CLEAN:       fir.do_loop %[[IV:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
-! CLEAN-NOT:     iter_args
-! CLEAN:         %[[IV_CVT:.*]] = fir.convert %[[IV]] : (index) -> i32
-! CLEAN:         fir.store %[[IV_CVT]] to %[[I_DECL]]#0 : !fir.ref<i32>
+! Clean lowering: nested loop has no iter_arg; the post-loop value is computed
+! as lb + tripCount*step after the loop and stored to the DO variable.
+! CLEAN:             fir.do_loop %{{.*}} = %[[LB:.*]] to %[[UB:.*]] step %[[ST:.*]] {
+! CLEAN-NOT:           iter_args
+! CLEAN:             }
+! CLEAN:             %[[DIFF:.*]] = arith.subi %{{.*}}, %{{.*}} overflow<nsw> : i32
+! CLEAN:             %[[ADD:.*]] = arith.addi %[[DIFF]], %{{.*}} overflow<nsw> : i32
+! CLEAN:             %[[TRIP:.*]] = arith.divsi %[[ADD]], %{{.*}} : i32
+! CLEAN:             %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %{{.*}} : i32
+! CLEAN:             %[[SEL:.*]] = arith.select %[[CMP]], %{{.*}}, %[[TRIP]] : i32
+! CLEAN:             %[[MUL:.*]] = arith.muli %[[SEL]], %{{.*}} overflow<nsw> : i32
+! CLEAN:             %[[LAST:.*]] = arith.addi %{{.*}}, %[[MUL]] overflow<nsw> : i32
+! CLEAN:             fir.store %[[LAST]] to %[[J_DECL]]#0 : !fir.ref<i32>

>From 7ef8c3b66207802345a0da707957fbe99c469b08 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Tue, 30 Jun 2026 14:27:53 -0700
Subject: [PATCH 04/12] [flang][test] Tighten checks and add non-nested
 negative case

Chain the post-loop value operands through captured SSA names instead of
wildcards, and add a plain DO loop outside any DO CONCURRENT to confirm it
keeps its iter_arg when the option is enabled.
---
 .../do_concurrent_clean_nested_loops.f90      | 43 ++++++++++++++-----
 1 file changed, 32 insertions(+), 11 deletions(-)

diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
index 6dfe9a58992c7..eee4b26117e65 100644
--- a/flang/test/Lower/do_concurrent_clean_nested_loops.f90
+++ b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
@@ -1,7 +1,8 @@
 ! Test -fdo-concurrent-clean-nested-loops: a plain DO loop nested in a DO
 ! CONCURRENT body is lowered without the secondary-induction iter_arg (the DO
 ! variable is recomputed from the induction variable), while the Fortran
-! post-loop value of the DO variable is still materialized after the loop.
+! post-loop value of the DO variable is still materialized after the loop. A
+! plain DO loop that is not nested in a DO CONCURRENT body is unaffected.
 
 ! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=CHECK,DEFAULT
 ! RUN: bbc -emit-hlfir -fdo-concurrent-clean-nested-loops -o - %s | FileCheck %s --check-prefixes=CHECK,CLEAN
@@ -27,16 +28,36 @@ subroutine nested(a, n)
 ! DEFAULT:           %[[RES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
 ! DEFAULT:           fir.store %[[RES]] to %[[J_DECL]]#0 : !fir.ref<i32>
 
-! Clean lowering: nested loop has no iter_arg; the post-loop value is computed
-! as lb + tripCount*step after the loop and stored to the DO variable.
-! CLEAN:             fir.do_loop %{{.*}} = %[[LB:.*]] to %[[UB:.*]] step %[[ST:.*]] {
+! Clean lowering: nested loop has no iter_arg and the body recomputes the DO
+! variable from the induction variable; the post-loop value is computed as
+! lb + tripCount*step after the loop and stored to the DO variable.
+! CLEAN:             fir.do_loop %{{.*}} = %[[LB:[^ ]+]] to %[[UB:[^ ]+]] step %[[ST:[^ ]+]] {
 ! CLEAN-NOT:           iter_args
+! CLEAN:               %[[IV:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CLEAN:               fir.store %[[IV]] to %[[J_DECL]]#0 : !fir.ref<i32>
 ! CLEAN:             }
-! CLEAN:             %[[DIFF:.*]] = arith.subi %{{.*}}, %{{.*}} overflow<nsw> : i32
-! CLEAN:             %[[ADD:.*]] = arith.addi %[[DIFF]], %{{.*}} overflow<nsw> : i32
-! CLEAN:             %[[TRIP:.*]] = arith.divsi %[[ADD]], %{{.*}} : i32
-! CLEAN:             %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %{{.*}} : i32
-! CLEAN:             %[[SEL:.*]] = arith.select %[[CMP]], %{{.*}}, %[[TRIP]] : i32
-! CLEAN:             %[[MUL:.*]] = arith.muli %[[SEL]], %{{.*}} overflow<nsw> : i32
-! CLEAN:             %[[LAST:.*]] = arith.addi %{{.*}}, %[[MUL]] overflow<nsw> : i32
+! CLEAN:             %[[LBI:.*]] = fir.convert %[[LB]] : (index) -> i32
+! CLEAN:             %[[UBI:.*]] = fir.convert %[[UB]] : (index) -> i32
+! CLEAN:             %[[STI:.*]] = fir.convert %[[ST]] : (index) -> i32
+! CLEAN:             %[[C0:.*]] = arith.constant 0 : i32
+! CLEAN:             %[[DIFF:.*]] = arith.subi %[[UBI]], %[[LBI]] overflow<nsw> : i32
+! CLEAN:             %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STI]] overflow<nsw> : i32
+! CLEAN:             %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STI]] : i32
+! CLEAN:             %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CLEAN:             %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CLEAN:             %[[MUL:.*]] = arith.muli %[[SEL]], %[[STI]] overflow<nsw> : i32
+! CLEAN:             %[[LAST:.*]] = arith.addi %[[LBI]], %[[MUL]] overflow<nsw> : i32
 ! CLEAN:             fir.store %[[LAST]] to %[[J_DECL]]#0 : !fir.ref<i32>
+
+! A plain DO loop not nested in a DO CONCURRENT body keeps its iter_arg even
+! when the option is enabled.
+subroutine not_nested(x)
+  implicit none
+  integer :: x, j
+  do j = 1, 3
+  end do
+  x = j
+end subroutine
+
+! CHECK-LABEL:   func.func @_QPnot_nested
+! CLEAN:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {

>From fee51fc13af6f2e8a83006c5e5ae5cd7d84c21c8 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Tue, 30 Jun 2026 14:37:18 -0700
Subject: [PATCH 05/12] [flang][test] Add non-unit lower-bound/step nested case

Cover do j=2,8,2 so the post-loop value check exercises lb + tripCount*step
rather than an lb=1/step=1 special case.
---
 .../do_concurrent_clean_nested_loops.f90      | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
index eee4b26117e65..87b25aa0002e1 100644
--- a/flang/test/Lower/do_concurrent_clean_nested_loops.f90
+++ b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
@@ -49,6 +49,37 @@ subroutine nested(a, n)
 ! CLEAN:             %[[LAST:.*]] = arith.addi %[[LBI]], %[[MUL]] overflow<nsw> : i32
 ! CLEAN:             fir.store %[[LAST]] to %[[J_DECL]]#0 : !fir.ref<i32>
 
+! Non-unit lower bound and step: the post-loop value must still be lb +
+! tripCount*step (here 2 + 4*2 = 10), not a hard-coded lb=1/step=1 form.
+subroutine nested_stride(a, n)
+  implicit none
+  integer :: n, i, j
+  integer :: a(n)
+  do concurrent (i=1:n)
+    do j = 2, 8, 2
+    end do
+    a(i) = j
+  end do
+end subroutine
+
+! CHECK-LABEL:   func.func @_QPnested_stride
+! CHECK:           %[[SJ_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnested_strideEj"}
+! CLEAN:             fir.do_loop %{{.*}} = %[[SLB:[^ ]+]] to %[[SUB:[^ ]+]] step %[[SST:[^ ]+]] {
+! CLEAN-NOT:           iter_args
+! CLEAN:             }
+! CLEAN:             %[[SLBI:.*]] = fir.convert %[[SLB]] : (index) -> i32
+! CLEAN:             %[[SUBI:.*]] = fir.convert %[[SUB]] : (index) -> i32
+! CLEAN:             %[[SSTI:.*]] = fir.convert %[[SST]] : (index) -> i32
+! CLEAN:             %[[SC0:.*]] = arith.constant 0 : i32
+! CLEAN:             %[[SDIFF:.*]] = arith.subi %[[SUBI]], %[[SLBI]] overflow<nsw> : i32
+! CLEAN:             %[[SADD:.*]] = arith.addi %[[SDIFF]], %[[SSTI]] overflow<nsw> : i32
+! CLEAN:             %[[STRIP:.*]] = arith.divsi %[[SADD]], %[[SSTI]] : i32
+! CLEAN:             %[[SCMP:.*]] = arith.cmpi slt, %[[STRIP]], %[[SC0]] : i32
+! CLEAN:             %[[SSEL:.*]] = arith.select %[[SCMP]], %[[SC0]], %[[STRIP]] : i32
+! CLEAN:             %[[SMUL:.*]] = arith.muli %[[SSEL]], %[[SSTI]] overflow<nsw> : i32
+! CLEAN:             %[[SLAST:.*]] = arith.addi %[[SLBI]], %[[SMUL]] overflow<nsw> : i32
+! CLEAN:             fir.store %[[SLAST]] to %[[SJ_DECL]]#0 : !fir.ref<i32>
+
 ! A plain DO loop not nested in a DO CONCURRENT body keeps its iter_arg even
 ! when the option is enabled.
 subroutine not_nested(x)

>From b1ba90d0cc8221c45124a260765efde0689343e0 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Tue, 30 Jun 2026 15:00:24 -0700
Subject: [PATCH 06/12] [flang][test] Add descending-step case and DEFAULT
 stride checks

Cover do j=8,2,-2 (final j = 0) for the step<0 post-loop value, and add
DEFAULT (option-off) iter_arg checks for the non-unit-step cases so a
regression that applied clean lowering by default would be caught.
---
 .../do_concurrent_clean_nested_loops.f90      | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
index 87b25aa0002e1..416bf9d38f041 100644
--- a/flang/test/Lower/do_concurrent_clean_nested_loops.f90
+++ b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
@@ -64,6 +64,8 @@ subroutine nested_stride(a, n)
 
 ! CHECK-LABEL:   func.func @_QPnested_stride
 ! CHECK:           %[[SJ_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnested_strideEj"}
+! DEFAULT:           %[[SRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! DEFAULT:           fir.store %[[SRES]] to %[[SJ_DECL]]#0 : !fir.ref<i32>
 ! CLEAN:             fir.do_loop %{{.*}} = %[[SLB:[^ ]+]] to %[[SUB:[^ ]+]] step %[[SST:[^ ]+]] {
 ! CLEAN-NOT:           iter_args
 ! CLEAN:             }
@@ -80,6 +82,39 @@ subroutine nested_stride(a, n)
 ! CLEAN:             %[[SLAST:.*]] = arith.addi %[[SLBI]], %[[SMUL]] overflow<nsw> : i32
 ! CLEAN:             fir.store %[[SLAST]] to %[[SJ_DECL]]#0 : !fir.ref<i32>
 
+! Descending loop (step < 0): the same lb + tripCount*step formula must hold
+! (here 8 + 4*(-2) = 0).
+subroutine nested_stride_neg(a, n)
+  implicit none
+  integer :: n, i, j
+  integer :: a(n)
+  do concurrent (i=1:n)
+    do j = 8, 2, -2
+    end do
+    a(i) = j
+  end do
+end subroutine
+
+! CHECK-LABEL:   func.func @_QPnested_stride_neg
+! CHECK:           %[[NJ_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnested_stride_negEj"}
+! DEFAULT:           %[[NRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! DEFAULT:           fir.store %[[NRES]] to %[[NJ_DECL]]#0 : !fir.ref<i32>
+! CLEAN:             fir.do_loop %{{.*}} = %[[NLB:[^ ]+]] to %[[NUB:[^ ]+]] step %[[NST:[^ ]+]] {
+! CLEAN-NOT:           iter_args
+! CLEAN:             }
+! CLEAN:             %[[NLBI:.*]] = fir.convert %[[NLB]] : (index) -> i32
+! CLEAN:             %[[NUBI:.*]] = fir.convert %[[NUB]] : (index) -> i32
+! CLEAN:             %[[NSTI:.*]] = fir.convert %[[NST]] : (index) -> i32
+! CLEAN:             %[[NC0:.*]] = arith.constant 0 : i32
+! CLEAN:             %[[NDIFF:.*]] = arith.subi %[[NUBI]], %[[NLBI]] overflow<nsw> : i32
+! CLEAN:             %[[NADD:.*]] = arith.addi %[[NDIFF]], %[[NSTI]] overflow<nsw> : i32
+! CLEAN:             %[[NTRIP:.*]] = arith.divsi %[[NADD]], %[[NSTI]] : i32
+! CLEAN:             %[[NCMP:.*]] = arith.cmpi slt, %[[NTRIP]], %[[NC0]] : i32
+! CLEAN:             %[[NSEL:.*]] = arith.select %[[NCMP]], %[[NC0]], %[[NTRIP]] : i32
+! CLEAN:             %[[NMUL:.*]] = arith.muli %[[NSEL]], %[[NSTI]] overflow<nsw> : i32
+! CLEAN:             %[[NLAST:.*]] = arith.addi %[[NLBI]], %[[NMUL]] overflow<nsw> : i32
+! CLEAN:             fir.store %[[NLAST]] to %[[NJ_DECL]]#0 : !fir.ref<i32>
+
 ! A plain DO loop not nested in a DO CONCURRENT body keeps its iter_arg even
 ! when the option is enabled.
 subroutine not_nested(x)

>From 538422b509acc8837fd057d86c2f6be062e8d2d3 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 6 Jul 2026 13:54:19 -0700
Subject: [PATCH 07/12] [flang][test] Add multi-IV do concurrent nested loop
 case

Confirm a DO CONCURRENT with multiple induction variables lowers to a
single fir.do_concurrent.loop (unaffected) while the nested plain DO loop
is still cleaned.
---
 .../do_concurrent_clean_nested_loops.f90      | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
index 416bf9d38f041..205f53ce00c9d 100644
--- a/flang/test/Lower/do_concurrent_clean_nested_loops.f90
+++ b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
@@ -115,6 +115,41 @@ subroutine nested_stride_neg(a, n)
 ! CLEAN:             %[[NLAST:.*]] = arith.addi %[[NLBI]], %[[NMUL]] overflow<nsw> : i32
 ! CLEAN:             fir.store %[[NLAST]] to %[[NJ_DECL]]#0 : !fir.ref<i32>
 
+! A DO CONCURRENT with multiple induction variables is lowered as a single
+! fir.do_concurrent.loop carrying all the IVs (unaffected by the option); only
+! the nested plain DO loop is cleaned.
+subroutine multi_iv(a, n, m)
+  implicit none
+  integer :: n, m, i, j, k
+  integer :: a(n, m)
+  do concurrent (i=1:n, j=1:m)
+    do k = 1, 3
+      a(i, j) = a(i, j) + k
+    end do
+  end do
+end subroutine
+
+! CHECK-LABEL:   func.func @_QPmulti_iv
+! CHECK:           %[[MK_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFmulti_ivEk"}
+! CHECK:           fir.do_concurrent.loop (%{{[^)]*}}, %{{[^)]*}}) = (%{{[^)]*}}, %{{[^)]*}}) to (%{{[^)]*}}, %{{[^)]*}}) step (%{{[^)]*}}, %{{[^)]*}}) {
+! DEFAULT:           %[[MRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! DEFAULT:           fir.store %[[MRES]] to %[[MK_DECL]]#0 : !fir.ref<i32>
+! CLEAN:             fir.do_loop %{{.*}} = %[[MLB:[^ ]+]] to %[[MUB:[^ ]+]] step %[[MST:[^ ]+]] {
+! CLEAN-NOT:           iter_args
+! CLEAN:             }
+! CLEAN:             %[[MLBI:.*]] = fir.convert %[[MLB]] : (index) -> i32
+! CLEAN:             %[[MUBI:.*]] = fir.convert %[[MUB]] : (index) -> i32
+! CLEAN:             %[[MSTI:.*]] = fir.convert %[[MST]] : (index) -> i32
+! CLEAN:             %[[MC0:.*]] = arith.constant 0 : i32
+! CLEAN:             %[[MDIFF:.*]] = arith.subi %[[MUBI]], %[[MLBI]] overflow<nsw> : i32
+! CLEAN:             %[[MADD:.*]] = arith.addi %[[MDIFF]], %[[MSTI]] overflow<nsw> : i32
+! CLEAN:             %[[MTRIP:.*]] = arith.divsi %[[MADD]], %[[MSTI]] : i32
+! CLEAN:             %[[MCMP:.*]] = arith.cmpi slt, %[[MTRIP]], %[[MC0]] : i32
+! CLEAN:             %[[MSEL:.*]] = arith.select %[[MCMP]], %[[MC0]], %[[MTRIP]] : i32
+! CLEAN:             %[[MMUL:.*]] = arith.muli %[[MSEL]], %[[MSTI]] overflow<nsw> : i32
+! CLEAN:             %[[MLAST:.*]] = arith.addi %[[MLBI]], %[[MMUL]] overflow<nsw> : i32
+! CLEAN:             fir.store %[[MLAST]] to %[[MK_DECL]]#0 : !fir.ref<i32>
+
 ! A plain DO loop not nested in a DO CONCURRENT body keeps its iter_arg even
 ! when the option is enabled.
 subroutine not_nested(x)

>From 8e8ceaf82ef272b57012065e192c561cd24ff639 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 6 Jul 2026 13:59:33 -0700
Subject: [PATCH 08/12] [flang][test] Cover DO CONCURRENT nested within cleaned
 loops

Add cases for a DO CONCURRENT nested inside a cleaned plain DO loop, and a
plain DO loop nested inside such an inner DO CONCURRENT, confirming each
concurrent header is preserved and every sequential loop is cleaned.
---
 .../do_concurrent_clean_nested_loops.f90      | 51 +++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
index 205f53ce00c9d..decc6724a2c1b 100644
--- a/flang/test/Lower/do_concurrent_clean_nested_loops.f90
+++ b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
@@ -150,6 +150,57 @@ subroutine multi_iv(a, n, m)
 ! CLEAN:             %[[MLAST:.*]] = arith.addi %[[MLBI]], %[[MMUL]] overflow<nsw> : i32
 ! CLEAN:             fir.store %[[MLAST]] to %[[MK_DECL]]#0 : !fir.ref<i32>
 
+! A DO CONCURRENT nested inside one of the cleaned plain DO loops is still
+! lowered as its own fir.do_concurrent.loop; the enclosing plain DO stays clean
+! and its post-loop value is materialized.
+subroutine dc_in_clean_loop(a, n, m)
+  implicit none
+  integer :: n, m, i, j, k
+  integer :: a(n)
+  do concurrent (i=1:n)
+    do j = 1, 3
+      do concurrent (k=1:m)
+        a(i) = a(i) + j*k
+      end do
+    end do
+  end do
+end subroutine
+
+! CHECK-LABEL:   func.func @_QPdc_in_clean_loop
+! CHECK:           %[[DJ_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFdc_in_clean_loopEj"}
+! CHECK:           fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
+! DEFAULT:           %[[DJRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! DEFAULT:           fir.store %[[DJRES]] to %[[DJ_DECL]]#0 : !fir.ref<i32>
+! CLEAN:             fir.do_loop %{{.*}} = %{{[^ ]+}} to %{{[^ ]+}} step %{{[^ ]+}} {
+! CLEAN:               fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
+! CLEAN:             %{{.*}} = arith.divsi %{{.*}}, %{{.*}} : i32
+! CLEAN:             fir.store %{{.*}} to %[[DJ_DECL]]#0 : !fir.ref<i32>
+
+! Plain DO loops inside a DO CONCURRENT that is itself nested in the body are
+! cleaned at any depth.
+subroutine loop_in_nested_dc(a, n, m, p)
+  implicit none
+  integer :: n, m, p, i, j, k, l
+  integer :: a(n)
+  do concurrent (i=1:n)
+    do j = 1, 3
+      do concurrent (k=1:m)
+        do l = 1, 4
+          a(i) = a(i) + j*k*l
+        end do
+      end do
+    end do
+  end do
+end subroutine
+
+! CHECK-LABEL:   func.func @_QPloop_in_nested_dc
+! CHECK:           fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
+! DEFAULT:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! DEFAULT:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! CLEAN:             fir.do_loop %{{.*}} = %{{[^ ]+}} to %{{[^ ]+}} step %{{[^ ]+}} {
+! CLEAN:               fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
+! CLEAN:                 fir.do_loop %{{.*}} = %{{[^ ]+}} to %{{[^ ]+}} step %{{[^ ]+}} {
+
 ! A plain DO loop not nested in a DO CONCURRENT body keeps its iter_arg even
 ! when the option is enabled.
 subroutine not_nested(x)

>From 4bf995e34c38ad3185c943c43a93b9f831f67128 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Tue, 7 Jul 2026 13:44:30 -0700
Subject: [PATCH 09/12] [flang] Lower all plain DO loops without
 secondary-induction iter_arg

Generalize the clean lowering to every structured DO loop: recompute the DO
variable from the induction variable in the body and materialize the Fortran
post-loop value after the loop. This removes the redundant loop-carried value
that hid memory recurrences from later analyses. Drops the now-unnecessary
DoConcurrentCleanNestedLoops option and regenerates the affected FIR goldens.
---
 flang/include/flang/Lower/LoweringOptions.def |   9 -
 flang/lib/Lower/Bridge.cpp                    | 100 ++------
 flang/test/Integration/ivdep.f90              |   6 -
 flang/test/Lower/OpenACC/acc-cache.f90        |   5 +-
 flang/test/Lower/OpenACC/acc-declare.f90      |  18 +-
 flang/test/Lower/OpenMP/default-clause.f90    |   4 +-
 .../Lower/OpenMP/hlfir-seqloop-parallel.f90   |  60 ++++-
 .../OpenMP/parallel-private-clause-fixes.f90  |  21 +-
 .../OpenMP/sections-predetermined-private.f90 |  34 ++-
 flang/test/Lower/OpenMP/shared-loop.f90       |  67 ++++--
 ...oop-reduction-allocatable-array-minmax.f90 |  21 +-
 flang/test/Lower/OpenMP/wsloop-variable.f90   |  21 +-
 flang/test/Lower/allocatable-polymorphic.f90  |   4 +-
 flang/test/Lower/dispatch.f90                 |  14 +-
 .../do_concurrent_clean_nested_loops.f90      | 215 ------------------
 .../do_concurrent_loop_in_nested_block.f90    |   5 +-
 flang/test/Lower/do_loop.f90                  | 170 ++++++++------
 flang/test/Lower/do_loop_unstructured.f90     |  20 +-
 flang/test/Lower/infinite_loop.f90            |  23 +-
 flang/test/Lower/inline_directive.f90         |   4 +-
 flang/test/Lower/ivdep.f90                    |  12 -
 flang/test/Lower/loops.f90                    |   4 +-
 flang/test/Lower/loops2.f90                   |  32 ++-
 flang/test/Lower/mixed_loops.f90              |  32 ++-
 flang/test/Lower/nsw.f90                      |   3 +-
 .../DoConcurrent/skip_all_nested_loops.f90    |   7 +-
 flang/tools/bbc/bbc.cpp                       |   8 -
 27 files changed, 414 insertions(+), 505 deletions(-)
 delete mode 100644 flang/test/Lower/do_concurrent_clean_nested_loops.f90

diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def
index 57a4a1adac239..0b02ffd5a3b22 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -93,14 +93,5 @@ ENUM_LOWERINGOPT(PreserveUseDebugInfo, unsigned, 1, 0)
 /// Portable, Extremum, ExtremeNum). Default: Legacy.
 ENUM_LOWERINGOPT(FPMaxminBehavior, Fortran::common::FPMaxminBehavior, 2, 0)
 
-/// If true, lower plain DO loops nested inside a DO CONCURRENT body without the
-/// secondary-induction iter_arg: the DO variable is recomputed from the
-/// induction variable in the body. This keeps the loop body free of a
-/// loop-carried value that would otherwise hide memory recurrences (e.g.
-/// reductions) from later analyses. The Fortran post-loop value of the DO
-/// variable is still materialized after the loop, so the lowering is
-/// semantics-preserving. Off by default.
-ENUM_LOWERINGOPT(DoConcurrentCleanNestedLoops, unsigned, 1, 0)
-
 #undef LOWERINGOPT
 #undef ENUM_LOWERINGOPT
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index e83e0c5e55741..34d1346d6b285 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2995,18 +2995,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     }
   }
 
-  /// Return true if the builder's current insertion point is within a
-  /// `fir.do_concurrent.loop` region (i.e. a plain DO loop being lowered here
-  /// is nested inside a DO CONCURRENT body).
-  bool isInsideDoConcurrentLoop() {
-    mlir::Block *block = builder->getInsertionBlock();
-    if (!block)
-      return false;
-    mlir::Operation *parentOp = block->getParentOp();
-    return parentOp && (mlir::isa<fir::DoConcurrentLoopOp>(parentOp) ||
-                        parentOp->getParentOfType<fir::DoConcurrentLoopOp>());
-  }
-
   /// Generate FIR to begin a structured or unstructured increment loop nest.
   void genFIRIncrementLoopBegin(
       IncrementLoopNestInfo &incrementLoopNestInfo,
@@ -3066,31 +3054,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         // recurrences (e.g. reductions) stay visible to later analyses. The DO
         // variable is recomputed from the induction variable in the body; its
         // post-loop value is materialized in genFIRIncrementLoopEnd.
-        if (getLoweringOptions().getDoConcurrentCleanNestedLoops() &&
-            isInsideDoConcurrentLoop()) {
-          auto loopOp = fir::DoLoopOp::create(
-              *builder, loc, lowerValue, upperValue, stepValue,
-              /*unordered=*/false, /*finalCountValue=*/false,
-              /*iterArgs=*/mlir::ValueRange{});
-          info.loopOp = loopOp;
-          builder->setInsertionPointToStart(loopOp.getBody());
-          mlir::Value loopValue = builder->createConvert(
-              loc, loopVarType, loopOp.getInductionVar());
-          fir::StoreOp::create(*builder, loc, loopValue, info.loopVariable);
-          addLoopAnnotationAttr(info, dirs);
-          continue;
-        }
-
         auto loopOp = fir::DoLoopOp::create(
             *builder, loc, lowerValue, upperValue, stepValue,
-            /*unordered=*/false,
-            /*finalCountValue=*/false,
-            builder->createConvert(loc, loopVarType, lowerValue));
+            /*unordered=*/false, /*finalCountValue=*/false,
+            /*iterArgs=*/mlir::ValueRange{});
         info.loopOp = loopOp;
         builder->setInsertionPointToStart(loopOp.getBody());
-        mlir::Value loopValue = loopOp.getRegionIterArgs()[0];
-
-        // Update the loop variable value in case it has non-index references.
+        mlir::Value loopValue =
+            builder->createConvert(loc, loopVarType, loopOp.getInductionVar());
         fir::StoreOp::create(*builder, loc, loopValue, info.loopVariable);
         addLoopAnnotationAttr(info, dirs);
         continue;
@@ -3232,50 +3203,29 @@ class FirConverter : public Fortran::lower::AbstractConverter {
           continue;
         }
 
-        // End fir.do_loop.
-        // Decrement tripVariable.
+        // End fir.do_loop. The loop carries no secondary-induction iter_arg, so
+        // materialize the Fortran post-loop value lb + tripCount*step after the
+        // loop for later uses of the DO variable.
         auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp);
-        // Iter_arg-free loop (DoConcurrentCleanNestedLoops): nothing to step in
-        // the body. Materialize the Fortran post-loop value lb + tripCount*step
-        // after the loop so later uses of the DO variable stay correct.
-        if (doLoopOp.getNumRegionIterArgs() == 0) {
-          builder->setInsertionPointAfter(doLoopOp);
-          mlir::Type type = info.getLoopVariableType();
-          mlir::Value lb =
-              builder->createConvert(loc, type, doLoopOp.getLowerBound());
-          mlir::Value ub =
-              builder->createConvert(loc, type, doLoopOp.getUpperBound());
-          mlir::Value st =
-              builder->createConvert(loc, type, doLoopOp.getStep());
-          mlir::Value zero = builder->createIntegerConstant(loc, type, 0);
-          mlir::Value trip =
-              mlir::arith::SubIOp::create(*builder, loc, ub, lb, iofAttr);
-          trip = mlir::arith::AddIOp::create(*builder, loc, trip, st, iofAttr);
-          trip = mlir::arith::DivSIOp::create(*builder, loc, trip, st);
-          mlir::Value empty = mlir::arith::CmpIOp::create(
-              *builder, loc, mlir::arith::CmpIPredicate::slt, trip, zero);
-          trip =
-              mlir::arith::SelectOp::create(*builder, loc, empty, zero, trip);
-          mlir::Value last =
-              mlir::arith::MulIOp::create(*builder, loc, trip, st, iofAttr);
-          last = mlir::arith::AddIOp::create(*builder, loc, lb, last, iofAttr);
-          fir::StoreOp::create(*builder, loc, last, info.loopVariable);
-          continue;
-        }
-        builder->setInsertionPointToEnd(doLoopOp.getBody());
-        // Step loopVariable to help optimizations such as vectorization.
-        // Induction variable elimination will clean up as necessary.
-        mlir::Value step = builder->createConvert(
-            loc, info.getLoopVariableType(), doLoopOp.getStep());
-        mlir::Value loopVar =
-            fir::LoadOp::create(*builder, loc, info.loopVariable);
-        mlir::Value loopVarInc =
-            mlir::arith::AddIOp::create(*builder, loc, loopVar, step, iofAttr);
-        fir::ResultOp::create(*builder, loc, loopVarInc);
         builder->setInsertionPointAfter(doLoopOp);
-        // The loop control variable may be used after the loop.
-        fir::StoreOp::create(*builder, loc, doLoopOp.getResult(0),
-                             info.loopVariable);
+        mlir::Type type = info.getLoopVariableType();
+        mlir::Value lb =
+            builder->createConvert(loc, type, doLoopOp.getLowerBound());
+        mlir::Value ub =
+            builder->createConvert(loc, type, doLoopOp.getUpperBound());
+        mlir::Value st = builder->createConvert(loc, type, doLoopOp.getStep());
+        mlir::Value zero = builder->createIntegerConstant(loc, type, 0);
+        mlir::Value trip =
+            mlir::arith::SubIOp::create(*builder, loc, ub, lb, iofAttr);
+        trip = mlir::arith::AddIOp::create(*builder, loc, trip, st, iofAttr);
+        trip = mlir::arith::DivSIOp::create(*builder, loc, trip, st);
+        mlir::Value empty = mlir::arith::CmpIOp::create(
+            *builder, loc, mlir::arith::CmpIPredicate::slt, trip, zero);
+        trip = mlir::arith::SelectOp::create(*builder, loc, empty, zero, trip);
+        mlir::Value last =
+            mlir::arith::MulIOp::create(*builder, loc, trip, st, iofAttr);
+        last = mlir::arith::AddIOp::create(*builder, loc, lb, last, iofAttr);
+        fir::StoreOp::create(*builder, loc, last, info.loopVariable);
         continue;
       }
 
diff --git a/flang/test/Integration/ivdep.f90 b/flang/test/Integration/ivdep.f90
index d72ab23af7ad2..9882fe148262f 100644
--- a/flang/test/Integration/ivdep.f90
+++ b/flang/test/Integration/ivdep.f90
@@ -16,8 +16,6 @@ subroutine ivdep_test1
      !CHECK: %[[VAL_13:.*]] = add nuw nsw i64 %[[VAL_12]], 0
      !CHECK: %[[VAL_14:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_13]]
      !CHECK: store i32 %[[VAL_8]], ptr %[[VAL_14]], align 4, !llvm.access.group [[DISTRINCT]]
-     !CHECK: %[[VAL_15:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT]]
-     !CHECK: %[[VAL_16:.*]] = add nsw i32 %[[VAL_15]], 1
      !CHECK: %[[VAL_17:.*]] = sub i64 {{.*}}, 1
      !CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION:.*]]
   end do
@@ -54,8 +52,6 @@ subroutine ivdep_test2
      !CHECK: %[[VAL_28:.*]] = add nuw nsw i64 %[[VAL_27]], 0
      !CHECK: %[[VAL_29:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_28]]
      !CHECK: store i32 %[[VAL_24]], ptr %[[VAL_29]], align 4, !llvm.access.group [[DISTRINCT1]]
-     !CHECK: %[[VAL_30:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]] 
-     !CHECK: %[[VAL_31:.*]] = add nsw i32 %[[VAL_30]], 1
      !CHECK: %[[VAL_32:.*]] = sub i64 {{.*}}, 1
      !CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION1:.*]]
   end do
@@ -93,8 +89,6 @@ subroutine ivdep_test3
      !CHECK: %[[VAL_29:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_28]]
      !CHECK: store i32 %[[VAL_24]], ptr %[[VAL_29]], align 4, !llvm.access.group [[DISTRINCT2]]
      !CHECK: call void @_QFivdep_test3Pfoo(), !llvm.access.group [[DISTRINCT2]]
-     !CHECK: %[[VAL_30:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]] 
-     !CHECK: %[[VAL_31:.*]] = add nsw i32 %[[VAL_30]], 1
      !CHECK: %[[VAL_32:.*]] = sub i64 {{.*}}, 1
      !CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION2:.*]]
   end do
diff --git a/flang/test/Lower/OpenACC/acc-cache.f90 b/flang/test/Lower/OpenACC/acc-cache.f90
index eb32f3b704198..03e06467f694d 100644
--- a/flang/test/Lower/OpenACC/acc-cache.f90
+++ b/flang/test/Lower/OpenACC/acc-cache.f90
@@ -242,9 +242,10 @@ subroutine test_cache_2d_loop_vars()
 ! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtest_cache_2d_loop_varsEi"}
 ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
 ! Inner loop j (non-acc loop, fir.do_loop)
-! CHECK: fir.do_loop %[[J_IV:.*]] = {{.*}} iter_args(%[[J_ITER:.*]] = {{.*}})
+! CHECK: fir.do_loop %[[J_IV:.*]] = {{.*}} to {{.*}} step {{.*}} {
 ! Inner loop iterator j is stored to j variable
-! CHECK: fir.store %[[J_ITER]] to %[[J_REF:.*]] : !fir.ref<i32>
+! CHECK: %[[J_CONV:.*]] = fir.convert %[[J_IV]] : (index) -> i32
+! CHECK: fir.store %[[J_CONV]] to %[[J_REF:.*]] : !fir.ref<i32>
 ! Dimension 1 bounds from j: lowerbound = j-1, upperbound = j
 ! CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index)
 ! Dimension 2 bounds from i: lowerbound = i-1, upperbound = i
diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90
index 349f5c84d5316..5f87a784eaf30 100644
--- a/flang/test/Lower/OpenACC/acc-declare.f90
+++ b/flang/test/Lower/OpenACC/acc-declare.f90
@@ -20,7 +20,7 @@ subroutine acc_declare_copy()
 ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare<dataClause =  acc_copy>, uniq_name = "_QMacc_declareFacc_declare_copyEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
 ! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copy>, name = "a"}
 ! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 ! CHECK: }
 ! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>)
 ! CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref<!fir.array<100xi32>>) to varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) {dataClause = #acc<data_clause acc_copy>, name = "a"}
@@ -40,7 +40,7 @@ subroutine acc_declare_create()
 ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare<dataClause =  acc_create>, uniq_name = "_QMacc_declareFacc_declare_createEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
 ! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
 ! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 ! CHECK: }
 ! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
 ! CHECK: acc.delete accPtr(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>) {dataClause = #acc<data_clause acc_create>, name = "a"}
@@ -60,7 +60,7 @@ subroutine acc_declare_present(a)
 ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause =  acc_present>, uniq_name = "_QMacc_declareFacc_declare_presentEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
 ! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
 ! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[PRESENT]] : !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32)
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 ! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[PRESENT]] : !fir.ref<!fir.array<100xi32>>)
 ! CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref<!fir.array<100xi32>>) {dataClause = #acc<data_clause acc_present>, name = "a"}
 
@@ -98,7 +98,7 @@ subroutine acc_declare_copyin()
 ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[ADECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
 ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[BDECL]]#0 : !fir.ref<!fir.array<10xi32>>) -> !fir.ref<!fir.array<10xi32>> {dataClause = #acc<data_clause acc_copyin_readonly>, name = "b"}
 ! CHECK: acc.declare_enter dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<10xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32)
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 ! CHECK: acc.delete accPtr(%[[COPYIN_A]] : !fir.ref<!fir.array<100xi32>>) {dataClause = #acc<data_clause acc_copyin>, name = "a"}
 ! CHECK: acc.delete accPtr(%[[COPYIN_B]] : !fir.ref<!fir.array<10xi32>>) {dataClause = #acc<data_clause acc_copyin_readonly>, name = "b"}
 
@@ -116,7 +116,7 @@ subroutine acc_declare_copyout()
 ! CHECK: %[[ADECL:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) {acc.declare = #acc.declare<dataClause =  acc_copyout>, uniq_name = "_QMacc_declareFacc_declare_copyoutEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
 ! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"}
 ! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32)
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 ! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>)
 ! CHECK: acc.copyout accPtr(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>) to varPtr(%[[ADECL]]#0 : !fir.ref<!fir.array<100xi32>>) {name = "a"}
 ! CHECK: return
@@ -135,7 +135,7 @@ subroutine acc_declare_deviceptr(a)
 ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause =  acc_deviceptr>, uniq_name = "_QMacc_declareFacc_declare_deviceptrEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
 ! CHECK: %[[DEVICEPTR:.*]] = acc.deviceptr varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
 ! CHECK: acc.declare_enter dataOperands(%[[DEVICEPTR]] : !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32)
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 
   subroutine acc_declare_link(a)
     integer :: a(100), i
@@ -151,7 +151,7 @@ subroutine acc_declare_link(a)
 ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause =  acc_declare_link>, uniq_name = "_QMacc_declareFacc_declare_linkEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
 ! CHECK: %[[LINK:.*]] = acc.declare_link varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
 ! CHECK: acc.declare_enter dataOperands(%[[LINK]] : !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32)
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 
   subroutine acc_declare_device_resident(a)
     integer :: a(100), i
@@ -167,7 +167,7 @@ subroutine acc_declare_device_resident(a)
 ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {acc.declare = #acc.declare<dataClause =  acc_declare_device_resident>, uniq_name = "_QMacc_declareFacc_declare_device_residentEa"} : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
 ! CHECK: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {name = "a"}
 ! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (i32)
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 ! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>)
 ! CHECK: acc.delete accPtr(%[[DEVICERES]] : !fir.ref<!fir.array<100xi32>>) {dataClause = #acc<data_clause acc_declare_device_resident>, name = "a"}
 
@@ -296,7 +296,7 @@ subroutine acc_declare_multiple_directive(a, b)
 ! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL_A]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copy>, name = "a"}
 ! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DECL_B]]#0 : !fir.ref<!fir.array<100xi32>>) -> !fir.ref<!fir.array<100xi32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"}
 ! CHECK: acc.declare_enter dataOperands(%[[COPYIN]], %[[CREATE]] : !fir.ref<!fir.array<100xi32>>, !fir.ref<!fir.array<100xi32>>)
-! CHECK: %{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! CHECK: fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
 
 
 ! CHECK: acc.copyout accPtr(%[[CREATE]] : !fir.ref<!fir.array<100xi32>>) to varPtr(%[[DECL_B]]#0 : !fir.ref<!fir.array<100xi32>>) {name = "b"}
diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90
index c16d19c129b8f..511abf64c202f 100644
--- a/flang/test/Lower/OpenMP/default-clause.f90
+++ b/flang/test/Lower/OpenMP/default-clause.f90
@@ -463,12 +463,12 @@ subroutine nested_constructs
 
 !CHECK: %[[INNER_J_DECL:.*]]:2 = hlfir.declare %[[INNER_J]] {{.*}}
     !$omp parallel default(private) firstprivate(y)
-!CHECK: {{.*}} = fir.do_loop {{.*}} {
+!CHECK: fir.do_loop {{.*}} {
       do i = 1, 10
 !CHECK: %[[CONST_1:.*]] = arith.constant 1 : i32
 !CHECK: hlfir.assign %[[CONST_1]] to %[[INNER_Y_DECL]]#0 : i32, !fir.ref<i32>
         y = 1
-!CHECK: {{.*}} = fir.do_loop {{.*}} {
+!CHECK: fir.do_loop {{.*}} {
         do j = 1, 10
 !CHECK: %[[CONST_20:.*]] = arith.constant 20 : i32
 !CHECK: hlfir.assign %[[CONST_20]] to %[[INNER_Z_DECL]]#0 : i32, !fir.ref<i32>
diff --git a/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90 b/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
index 7324b3c49fd6f..4b73ce2fd1016 100644
--- a/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
+++ b/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
@@ -22,9 +22,21 @@ subroutine sb1
 !CHECK:    %[[I_DECL:.*]]:2 = hlfir.declare %[[I_ADDR]] {uniq_name = "_QFsb1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 !CHECK:    omp.parallel private({{.*}} %[[I_DECL]]#0 -> %[[I_PVT_ADDR:.*]] : {{.*}}) {
 !CHECK:      %[[I_PVT_DECL:.*]]:2 = hlfir.declare %[[I_PVT_ADDR]] {uniq_name = "_QFsb1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
-!CHECK:      %[[I_FINAL_VAL:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[I_VAL:.*]] = %{{.*}}) -> (i32) {
+!CHECK:      fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:        %[[I_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
 !CHECK:        fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      }
+!CHECK:      %[[I_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      %[[I_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      %[[I_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      %[[I_C0:.*]] = arith.constant 0 : i32
+!CHECK:      %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] overflow<nsw> : i32
+!CHECK:      %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] overflow<nsw> : i32
+!CHECK:      %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : i32
+!CHECK:      %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : i32
+!CHECK:      %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : i32
+!CHECK:      %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] overflow<nsw> : i32
+!CHECK:      %[[I_FINAL_VAL:.*]] = arith.addi %[[I_LB]], %[[I_M]] overflow<nsw> : i32
 !CHECK:      fir.store %[[I_FINAL_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      omp.terminator
 !CHECK:    }
@@ -58,19 +70,55 @@ subroutine sb2
 
 !CHECK:      %[[I_PVT_DECL:.*]]:2 = hlfir.declare %[[I_PVT_ADDR]] {uniq_name = "_QFsb2Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 
-!CHECK:      %[[FINAL_J_VAL:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[J_VAL:.*]] = %{{.*}}) -> (i32) {
+!CHECK:      fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:        %[[J_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
 !CHECK:        fir.store %[[J_VAL]] to %[[J_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        fir.if %{{.*}} {
-!CHECK:          %[[FINAL_I_VAL:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[I_VAL:.*]] = %{{.*}}) -> (i32) {
+!CHECK:          fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:            %[[I_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
 !CHECK:            fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:          }
+!CHECK:          %[[I_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:          %[[I_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:          %[[I_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:          %[[I_C0:.*]] = arith.constant 0 : i32
+!CHECK:          %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] overflow<nsw> : i32
+!CHECK:          %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] overflow<nsw> : i32
+!CHECK:          %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : i32
+!CHECK:          %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : i32
+!CHECK:          %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : i32
+!CHECK:          %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] overflow<nsw> : i32
+!CHECK:          %[[FINAL_I_VAL:.*]] = arith.addi %[[I_LB]], %[[I_M]] overflow<nsw> : i32
 !CHECK:          fir.store %[[FINAL_I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        }
-!CHECK:        %[[FINAL_I_VAL:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[I_VAL:.*]] = %{{.*}}) -> (i32) {
-!CHECK:          fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
+!CHECK:        fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:          %[[I_VAL2:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:          fir.store %[[I_VAL2]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        }
-!CHECK:        fir.store %[[FINAL_I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
+!CHECK:        %[[I2_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:        %[[I2_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:        %[[I2_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:        %[[I2_C0:.*]] = arith.constant 0 : i32
+!CHECK:        %[[I2_D:.*]] = arith.subi %[[I2_UB]], %[[I2_LB]] overflow<nsw> : i32
+!CHECK:        %[[I2_A:.*]] = arith.addi %[[I2_D]], %[[I2_ST]] overflow<nsw> : i32
+!CHECK:        %[[I2_TR:.*]] = arith.divsi %[[I2_A]], %[[I2_ST]] : i32
+!CHECK:        %[[I2_CMP:.*]] = arith.cmpi slt, %[[I2_TR]], %[[I2_C0]] : i32
+!CHECK:        %[[I2_SEL:.*]] = arith.select %[[I2_CMP]], %[[I2_C0]], %[[I2_TR]] : i32
+!CHECK:        %[[I2_M:.*]] = arith.muli %[[I2_SEL]], %[[I2_ST]] overflow<nsw> : i32
+!CHECK:        %[[FINAL_I_VAL2:.*]] = arith.addi %[[I2_LB]], %[[I2_M]] overflow<nsw> : i32
+!CHECK:        fir.store %[[FINAL_I_VAL2]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      }
+!CHECK:      %[[J_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      %[[J_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      %[[J_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      %[[J_C0:.*]] = arith.constant 0 : i32
+!CHECK:      %[[J_D:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
+!CHECK:      %[[J_A:.*]] = arith.addi %[[J_D]], %[[J_ST]] overflow<nsw> : i32
+!CHECK:      %[[J_TR:.*]] = arith.divsi %[[J_A]], %[[J_ST]] : i32
+!CHECK:      %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TR]], %[[J_C0]] : i32
+!CHECK:      %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TR]] : i32
+!CHECK:      %[[J_M:.*]] = arith.muli %[[J_SEL]], %[[J_ST]] overflow<nsw> : i32
+!CHECK:      %[[FINAL_J_VAL:.*]] = arith.addi %[[J_LB]], %[[J_M]] overflow<nsw> : i32
 !CHECK:      fir.store %[[FINAL_J_VAL]] to %[[J_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      omp.terminator
 !CHECK:    }
diff --git a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
index e2fbd8b7d1ac9..a061d897456bd 100644
--- a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
+++ b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
@@ -58,20 +58,25 @@
 ! CHECK:               %[[VAL_9:.*]] = fir.load %[[GAMA_DECL]]#0 : !fir.ref<i32>
 ! CHECK:               %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index
 ! CHECK:               %[[VAL_11:.*]] = arith.constant 1 : index
-! CHECK:               %[[LB:.*]] = fir.convert %[[VAL_8]] : (index) -> i32
-! CHECK:               %[[VAL_12:.*]] = fir.do_loop %[[VAL_13:[^ ]*]] =
-! CHECK-SAME:              %[[VAL_8]] to %[[VAL_10]] step %[[VAL_11]]
-! CHECK-SAME:              iter_args(%[[IV:.*]] = %[[LB]]) -> (i32) {
+! CHECK:               fir.do_loop %[[VAL_13:[^ ]*]] = %[[VAL_8]] to %[[VAL_10]] step %[[VAL_11]] {
+! CHECK:                 %[[IV:.*]] = fir.convert %[[VAL_13]] : (index) -> i32
 ! CHECK:                 fir.store %[[IV]] to %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:                 %[[LOAD:.*]] = fir.load %[[PRIV_I_DECL]]#0 : !fir.ref<i32>
 ! CHECK:                 %[[VAL_15:.*]] = fir.load %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:                 %[[VAL_16:.*]] = arith.addi %[[LOAD]], %[[VAL_15]] : i32
 ! CHECK:                 hlfir.assign %[[VAL_16]] to %[[PRIV_X_DECL]]#0 : i32, !fir.ref<i32>
-! CHECK:                 %[[STEPCAST:.*]] = fir.convert %[[VAL_11]] : (index) -> i32
-! CHECK:                 %[[IVLOAD:.*]] = fir.load %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
-! CHECK:                 %[[IVINC:.*]] = arith.addi %[[IVLOAD]], %[[STEPCAST]] overflow<nsw> :
-! CHECK:                 fir.result %[[IVINC]] : i32
 ! CHECK:               }
+! CHECK:               %[[LB:.*]] = fir.convert %[[VAL_8]] : (index) -> i32
+! CHECK:               %[[UB:.*]] = fir.convert %[[VAL_10]] : (index) -> i32
+! CHECK:               %[[STEP:.*]] = fir.convert %[[VAL_11]] : (index) -> i32
+! CHECK:               %[[C0:.*]] = arith.constant 0 : i32
+! CHECK:               %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+! CHECK:               %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+! CHECK:               %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+! CHECK:               %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CHECK:               %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CHECK:               %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+! CHECK:               %[[VAL_12:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
 ! CHECK:               fir.store %[[VAL_12]] to %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:               omp.yield
 ! CHECK:             }
diff --git a/flang/test/Lower/OpenMP/sections-predetermined-private.f90 b/flang/test/Lower/OpenMP/sections-predetermined-private.f90
index 3313feb3d7021..aaf7c125e1b95 100644
--- a/flang/test/Lower/OpenMP/sections-predetermined-private.f90
+++ b/flang/test/Lower/OpenMP/sections-predetermined-private.f90
@@ -15,15 +15,41 @@
 ! CHECK:             %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 ! CHECK:             omp.sections {
 ! CHECK:               omp.section {
-! CHECK:                 %[[VAL_11:.*]] = fir.do_loop %[[VAL_12:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}} -> (i32) {
+! CHECK:                 fir.do_loop %[[VAL_12:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:                   %[[VAL_IV:.*]] = fir.convert %[[VAL_12]] : (index) -> i32
+! CHECK:                   fir.store %[[VAL_IV]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 }
-! CHECK:                 fir.store %[[VAL_11]] to %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:                 %[[LB1:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:                 %[[UB1:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:                 %[[ST1:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:                 %[[C01:.*]] = arith.constant 0 : i32
+! CHECK:                 %[[D1:.*]] = arith.subi %[[UB1]], %[[LB1]] overflow<nsw> : i32
+! CHECK:                 %[[A1:.*]] = arith.addi %[[D1]], %[[ST1]] overflow<nsw> : i32
+! CHECK:                 %[[TR1:.*]] = arith.divsi %[[A1]], %[[ST1]] : i32
+! CHECK:                 %[[CMP1:.*]] = arith.cmpi slt, %[[TR1]], %[[C01]] : i32
+! CHECK:                 %[[SEL1:.*]] = arith.select %[[CMP1]], %[[C01]], %[[TR1]] : i32
+! CHECK:                 %[[M1:.*]] = arith.muli %[[SEL1]], %[[ST1]] overflow<nsw> : i32
+! CHECK:                 %[[LAST1:.*]] = arith.addi %[[LB1]], %[[M1]] overflow<nsw> : i32
+! CHECK:                 fir.store %[[LAST1]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 omp.terminator
 ! CHECK:               }
 ! CHECK:               omp.section {
-! CHECK:                 %[[VAL_25:.*]] = fir.do_loop %[[VAL_26:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
+! CHECK:                 fir.do_loop %[[VAL_26:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:                   %[[VAL_IV2:.*]] = fir.convert %[[VAL_26]] : (index) -> i32
+! CHECK:                   fir.store %[[VAL_IV2]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 }
-! CHECK:                 fir.store %[[VAL_25]] to %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:                 %[[LB2:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:                 %[[UB2:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:                 %[[ST2:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:                 %[[C02:.*]] = arith.constant 0 : i32
+! CHECK:                 %[[D2:.*]] = arith.subi %[[UB2]], %[[LB2]] overflow<nsw> : i32
+! CHECK:                 %[[A2:.*]] = arith.addi %[[D2]], %[[ST2]] overflow<nsw> : i32
+! CHECK:                 %[[TR2:.*]] = arith.divsi %[[A2]], %[[ST2]] : i32
+! CHECK:                 %[[CMP2:.*]] = arith.cmpi slt, %[[TR2]], %[[C02]] : i32
+! CHECK:                 %[[SEL2:.*]] = arith.select %[[CMP2]], %[[C02]], %[[TR2]] : i32
+! CHECK:                 %[[M2:.*]] = arith.muli %[[SEL2]], %[[ST2]] overflow<nsw> : i32
+! CHECK:                 %[[LAST2:.*]] = arith.addi %[[LB2]], %[[M2]] overflow<nsw> : i32
+! CHECK:                 fir.store %[[LAST2]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 omp.terminator
 ! CHECK:               }
 ! CHECK:               omp.terminator
diff --git a/flang/test/Lower/OpenMP/shared-loop.f90 b/flang/test/Lower/OpenMP/shared-loop.f90
index eb277efb2d3de..42aefc932e54f 100644
--- a/flang/test/Lower/OpenMP/shared-loop.f90
+++ b/flang/test/Lower/OpenMP/shared-loop.f90
@@ -9,14 +9,23 @@
 ! CHECK:    omp.parallel {
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] =
-! CHECK:            fir.store %[[ARG1]] to %[[DECL_I]]#0
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
+! CHECK:            fir.store %[[IV]] to %[[DECL_I]]#0
 ! CHECK:            hlfir.assign
-! CHECK:            %[[LOAD_I:.*]] = fir.load %[[DECL_I]]#0
-! CHECK:            %[[RES_I:.*]] = arith.addi %[[LOAD_I]], %{{.*}}
-! CHECK:            fir.result %[[RES_I]]
 ! CHECK:          }
-! CHECK:          fir.store %[[RES]] to %[[DECL_I]]#0
+! CHECK:          %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[C0:.*]] = arith.constant 0 : i32
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : i32
+! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+! CHECK:          %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:          fir.store %[[LAST]] to %[[DECL_I]]#0
 ! CHECK:          omp.terminator
 ! CHECK:        }
 ! CHECK:        omp.terminator
@@ -47,15 +56,24 @@ subroutine omploop
 ! CHECK:      %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] =
-! CHECK-NOT:            fir.store %[[ARG1]] to %[[DECL_I]]#1
-! CHECK:            fir.store %[[ARG1]] to %[[DECL_PRIV_I]]#0
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
+! CHECK-NOT:            fir.store %{{.*}} to %[[DECL_I]]#1
+! CHECK:            fir.store %[[IV]] to %[[DECL_PRIV_I]]#0
 ! CHECK:            hlfir.assign
-! CHECK:            %[[LOAD_I:.*]] = fir.load %[[DECL_PRIV_I]]#0
-! CHECK:            %[[RES_I:.*]] = arith.addi %[[LOAD_I]], %{{.*}}
-! CHECK:            fir.result %[[RES_I]]
 ! CHECK:          }
-! CHECK:          fir.store %[[RES]] to %[[DECL_PRIV_I]]#0
+! CHECK:          %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[C0:.*]] = arith.constant 0 : i32
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : i32
+! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+! CHECK:          %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:          fir.store %[[LAST]] to %[[DECL_PRIV_I]]#0
 ! CHECK:          omp.terminator
 ! CHECK:        }
 ! CHECK:        omp.terminator
@@ -87,15 +105,24 @@ subroutine omploop2
 ! CHECK:      %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          %[[RES:.*]] = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] =
-! CHECK-NOT:            fir.store %[[ARG1]] to %[[DECL_I]]#1
-! CHECK:            fir.store %[[ARG1]] to %[[DECL_PRIV_I]]#0
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
+! CHECK-NOT:            fir.store %{{.*}} to %[[DECL_I]]#1
+! CHECK:            fir.store %[[IV]] to %[[DECL_PRIV_I]]#0
 ! CHECK:            hlfir.assign
-! CHECK:            %[[LOAD_I:.*]] = fir.load %[[DECL_PRIV_I]]#0
-! CHECK:            %[[RES_I:.*]] = arith.addi %[[LOAD_I]], %{{.*}}
-! CHECK:            fir.result %[[RES_I]]
 ! CHECK:          }
-! CHECK:          fir.store %[[RES]] to %[[DECL_PRIV_I]]#0
+! CHECK:          %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:          %[[C0:.*]] = arith.constant 0 : i32
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : i32
+! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+! CHECK:          %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:          fir.store %[[LAST]] to %[[DECL_PRIV_I]]#0
 ! CHECK:          omp.terminator
 ! CHECK:        }
 ! CHECK:        omp.terminator
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
index 07b472ed2ee5c..1a606f64a7d34 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
@@ -201,8 +201,8 @@ program reduce15
 ! CHECK:           %[[VAL_38:.*]] = arith.constant 10 : i32
 ! CHECK:           %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i32) -> index
 ! CHECK:           %[[VAL_40:.*]] = arith.constant 1 : index
-! CHECK:           %[[VAL_41:.*]] = fir.convert %[[VAL_37]] : (index) -> i32
-! CHECK:           %[[VAL_42:.*]] = fir.do_loop %[[VAL_43:.*]] = %[[VAL_37]] to %[[VAL_39]] step %[[VAL_40]] iter_args(%[[VAL_44:.*]] = %[[VAL_41]]) -> (i32) {
+! CHECK:           fir.do_loop %[[VAL_43:.*]] = %[[VAL_37]] to %[[VAL_39]] step %[[VAL_40]] {
+! CHECK:             %[[VAL_44:.*]] = fir.convert %[[VAL_43]] : (index) -> i32
 ! CHECK:             fir.store %[[VAL_44]] to %[[VAL_3]]#0 : !fir.ref<i32>
 ! CHECK:             %[[VAL_45:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
 ! CHECK:             %[[VAL_46:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
@@ -210,12 +210,19 @@ program reduce15
 ! CHECK:             %[[VAL_48:.*]] = fir.convert %[[VAL_47]] : (i32) -> i64
 ! CHECK:             %[[VAL_49:.*]] = hlfir.designate %[[VAL_46]] (%[[VAL_48]])  : (!fir.box<!fir.heap<!fir.array<?xi32>>>, i64) -> !fir.ref<i32>
 ! CHECK:             hlfir.assign %[[VAL_45]] to %[[VAL_49]] : i32, !fir.ref<i32>
-! CHECK:             %[[VAL_51:.*]] = fir.convert %[[VAL_40]] : (index) -> i32
-! CHECK:             %[[VAL_52:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
-! CHECK:             %[[VAL_53:.*]] = arith.addi %[[VAL_52]], %[[VAL_51]] overflow<nsw> : i32
-! CHECK:             fir.result %[[VAL_53]] : i32
 ! CHECK:           }
-! CHECK:           fir.store %[[VAL_54:.*]] to %[[VAL_3]]#0 : !fir.ref<i32>
+! CHECK:           %[[VAL_LB:.*]] = fir.convert %[[VAL_37]] : (index) -> i32
+! CHECK:           %[[VAL_UB:.*]] = fir.convert %[[VAL_39]] : (index) -> i32
+! CHECK:           %[[VAL_ST:.*]] = fir.convert %[[VAL_40]] : (index) -> i32
+! CHECK:           %[[VAL_C0:.*]] = arith.constant 0 : i32
+! CHECK:           %[[VAL_DIFF:.*]] = arith.subi %[[VAL_UB]], %[[VAL_LB]] overflow<nsw> : i32
+! CHECK:           %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_ST]] overflow<nsw> : i32
+! CHECK:           %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_ST]] : i32
+! CHECK:           %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : i32
+! CHECK:           %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : i32
+! CHECK:           %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_ST]] overflow<nsw> : i32
+! CHECK:           %[[VAL_54:.*]] = arith.addi %[[VAL_LB]], %[[VAL_MUL]] overflow<nsw> : i32
+! CHECK:           fir.store %[[VAL_54]] to %[[VAL_3]]#0 : !fir.ref<i32>
 ! CHECK:           omp.parallel {
 ! CHECK:             %[[VAL_57:.*]] = arith.constant 1 : i32
 ! CHECK:             %[[VAL_58:.*]] = arith.constant 10 : i32
diff --git a/flang/test/Lower/OpenMP/wsloop-variable.f90 b/flang/test/Lower/OpenMP/wsloop-variable.f90
index 60d970f3f0bac..02e47f7aa212e 100644
--- a/flang/test/Lower/OpenMP/wsloop-variable.f90
+++ b/flang/test/Lower/OpenMP/wsloop-variable.f90
@@ -138,8 +138,8 @@ subroutine wsloop_variable_sub
 !CHECK:               %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> index
 !CHECK:               %[[VAL_33:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32>
 !CHECK:               %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (i32) -> index
-!CHECK:               %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (index) -> i64
-!CHECK:               %[[VAL_36:.*]] = fir.do_loop %[[VAL_37:.*]] = %[[VAL_30]] to %[[VAL_32]] step %[[VAL_34]] iter_args(%[[VAL_38:.*]] = %[[VAL_35]]) -> (i64) {
+!CHECK:               fir.do_loop %[[VAL_37:.*]] = %[[VAL_30]] to %[[VAL_32]] step %[[VAL_34]] {
+!CHECK:                 %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (index) -> i64
 !CHECK:                 fir.store %[[VAL_38]] to %[[VAL_17]]#0 : !fir.ref<i64>
 !CHECK:                 %[[VAL_39:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i16>
 !CHECK:                 %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (i16) -> i64
@@ -147,12 +147,19 @@ subroutine wsloop_variable_sub
 !CHECK:                 %[[VAL_42:.*]] = arith.addi %[[VAL_40]], %[[VAL_41]] : i64
 !CHECK:                 %[[VAL_43:.*]] = fir.convert %[[VAL_42]] : (i64) -> f32
 !CHECK:                 hlfir.assign %[[VAL_43]] to %[[VAL_21]]#0 : f32, !fir.ref<f32>
-!CHECK:                 %[[VAL_45:.*]] = fir.convert %[[VAL_34]] : (index) -> i64
-!CHECK:                 %[[VAL_46:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<i64>
-!CHECK:                 %[[VAL_47:.*]] = arith.addi %[[VAL_46]], %[[VAL_45]] overflow<nsw> : i64
-!CHECK:                 fir.result %[[VAL_47]] : i64
 !CHECK:               }
-!CHECK:               fir.store %[[VAL_48:.*]] to %[[VAL_17]]#0 : !fir.ref<i64>
+!CHECK:               %[[VAL_LB:.*]] = fir.convert %[[VAL_30]] : (index) -> i64
+!CHECK:               %[[VAL_UB:.*]] = fir.convert %[[VAL_32]] : (index) -> i64
+!CHECK:               %[[VAL_ST:.*]] = fir.convert %[[VAL_34]] : (index) -> i64
+!CHECK:               %[[VAL_C0:.*]] = arith.constant 0 : i64
+!CHECK:               %[[VAL_DIFF:.*]] = arith.subi %[[VAL_UB]], %[[VAL_LB]] overflow<nsw> : i64
+!CHECK:               %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_ST]] overflow<nsw> : i64
+!CHECK:               %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_ST]] : i64
+!CHECK:               %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : i64
+!CHECK:               %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : i64
+!CHECK:               %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_ST]] overflow<nsw> : i64
+!CHECK:               %[[VAL_48:.*]] = arith.addi %[[VAL_LB]], %[[VAL_MUL]] overflow<nsw> : i64
+!CHECK:               fir.store %[[VAL_48]] to %[[VAL_17]]#0 : !fir.ref<i64>
 !CHECK:               omp.yield
 !CHECK:             }
 !CHECK:           }
diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90
index 9e4f04b45516e..8a0cb1bbc7033 100644
--- a/flang/test/Lower/allocatable-polymorphic.f90
+++ b/flang/test/Lower/allocatable-polymorphic.f90
@@ -332,12 +332,12 @@ subroutine test_allocatable()
 ! CHECK: %[[C2_REBOX:.*]] = fir.rebox %[[C2_LOAD2]] : (!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>) -> !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>
 ! CHECK: fir.dispatch "proc2"(%[[C2_REBOX]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) (%[[C2_REBOX]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32}
 
-! CHECK-LABEL: %{{.*}} = fir.do_loop
+! CHECK-LABEL: fir.do_loop
 ! CHECK: %[[C3_LOAD:.*]] = fir.load %[[C3_DECL]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>
 ! CHECK: %[[DESIGNATE_C3:.*]] = hlfir.designate %[[C3_LOAD]] (%{{.*}})  : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, i64) -> !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>
 ! CHECK: fir.dispatch "proc2"(%[[DESIGNATE_C3]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) (%[[DESIGNATE_C3]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32}
 
-! CHECK-LABEL: %{{.*}} = fir.do_loop
+! CHECK-LABEL: fir.do_loop
 ! CHECK: %[[C4_LOAD:.*]] = fir.load %[[C4_DECL]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>
 ! CHECK: %[[DESIGNATE_C4:.*]] = hlfir.designate %[[C4_LOAD]] (%{{.*}})  : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, i64) -> !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>
 ! CHECK: fir.dispatch "proc2"(%[[DESIGNATE_C4]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) (%[[DESIGNATE_C4]] : !fir.class<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32}
diff --git a/flang/test/Lower/dispatch.f90 b/flang/test/Lower/dispatch.f90
index a66287d2b4fd6..0dee190398ccc 100644
--- a/flang/test/Lower/dispatch.f90
+++ b/flang/test/Lower/dispatch.f90
@@ -250,11 +250,11 @@ subroutine check_dispatch_dynamic_array(p, t)
 ! CHECK-SAME: %[[ARG1:.*]]: !fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>> {fir.bindc_name = "t"}) {
 ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_arrayEp"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>)
 ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_arrayEt"} : (!fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>)
-! CHECK: %{{.*}} = fir.do_loop {{.*}} {
+! CHECK: fir.do_loop {{.*}} {
 ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[ARG0_DECL]]#0 (%{{.*}})  : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: fir.dispatch "tbp_pass"(%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32}
 
-! CHECK: %{{.*}} = fir.do_loop {{.*}} {
+! CHECK: fir.do_loop {{.*}} {
 ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[ARG1_DECL]]#0 (%{{.*}})  : (!fir.box<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, i64) -> !fir.ref<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: %[[EMBOX:.*]] = fir.embox %[[DESIGNATE]] : (!fir.ref<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) -> !fir.box<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: %[[CONV:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
@@ -278,12 +278,12 @@ subroutine check_dispatch_allocatable_array(p, t)
 ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "t"}) {
 ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_allocatable_arrayEp"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>)
 ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcall_dispatchFcheck_dispatch_allocatable_arrayEt"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>)
-! CHECK: %{{.*}} = fir.do_loop {{.*}} {
+! CHECK: fir.do_loop {{.*}} {
 ! CHECK: %[[LOAD_ARG0:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>
 ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[LOAD_ARG0]] (%{{.*}})  : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: fir.dispatch "tbp_pass"(%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32}
 
-! CHECK: %{{.*}} = fir.do_loop {{.*}} {
+! CHECK: fir.do_loop {{.*}} {
 ! CHECK: %[[LOAD_ARG1:.*]] = fir.load %[[ARG1_DECL]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>
 ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[LOAD_ARG1]] (%{{.*}})  : (!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, i64) -> !fir.ref<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: %[[EMBOX:.*]] = fir.embox %[[DESIGNATE]] : (!fir.ref<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) -> !fir.box<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
@@ -309,12 +309,12 @@ subroutine check_dispatch_pointer_array(p, t)
 ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_pointer_arrayEp"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>)
 ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMcall_dispatchFcheck_dispatch_pointer_arrayEt"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>)
 
-! CHECK: %{{.*}} = fir.do_loop {{.*}} {
+! CHECK: fir.do_loop {{.*}} {
 ! CHECK: %[[LOAD_ARG0:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>
 ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[LOAD_ARG0]] (%{{.*}})  : (!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: fir.dispatch "tbp_pass"(%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[DESIGNATE]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32}
 
-! CHECK: %{{.*}} = fir.do_loop {{.*}} {
+! CHECK: fir.do_loop {{.*}} {
 ! CHECK: %[[LOAD_ARG1:.*]] = fir.load %[[ARG1_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>>
 ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[LOAD_ARG1]] (%{{.*}})  : (!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>>, i64) -> !fir.ref<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: %[[EMBOX:.*]] = fir.embox %[[DESIGNATE]] : (!fir.ref<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) -> !fir.box<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
@@ -337,7 +337,7 @@ subroutine check_dispatch_dynamic_array_copy(p, o)
 ! CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_array_copyEo"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>)
 ! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMcall_dispatchFcheck_dispatch_dynamic_array_copyEp"} : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, !fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>)
 
-! CHECK: %{{.*}} = fir.do_loop {{.*}} {
+! CHECK: fir.do_loop {{.*}} {
 ! CHECK: %[[DESIGNATE0:.*]] = hlfir.designate %[[ARG0_DECL]]#0 (%{{.*}})  : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: %[[DESIGNATE1:.*]] = hlfir.designate %[[ARG1_DECL]]#0 (%{{.*}})  : (!fir.class<!fir.array<?x!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>>, i64) -> !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>
 ! CHECK: fir.dispatch "pass_with_class_arg"(%[[DESIGNATE0]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) (%[[DESIGNATE0]], %[[DESIGNATE1]] : !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMcall_dispatchTp1{a:i32,b:i32}>>) {pass_arg_pos = 0 : i32}
diff --git a/flang/test/Lower/do_concurrent_clean_nested_loops.f90 b/flang/test/Lower/do_concurrent_clean_nested_loops.f90
deleted file mode 100644
index decc6724a2c1b..0000000000000
--- a/flang/test/Lower/do_concurrent_clean_nested_loops.f90
+++ /dev/null
@@ -1,215 +0,0 @@
-! Test -fdo-concurrent-clean-nested-loops: a plain DO loop nested in a DO
-! CONCURRENT body is lowered without the secondary-induction iter_arg (the DO
-! variable is recomputed from the induction variable), while the Fortran
-! post-loop value of the DO variable is still materialized after the loop. A
-! plain DO loop that is not nested in a DO CONCURRENT body is unaffected.
-
-! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=CHECK,DEFAULT
-! RUN: bbc -emit-hlfir -fdo-concurrent-clean-nested-loops -o - %s | FileCheck %s --check-prefixes=CHECK,CLEAN
-
-subroutine nested(a, n)
-  implicit none
-  integer :: n, i, j
-  integer :: a(n)
-  do concurrent (i=1:n)
-    do j = 1, 3
-    end do
-    a(i) = j
-  end do
-end subroutine
-
-! CHECK-LABEL:   func.func @_QPnested
-! CHECK:           %[[J_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnestedEj"}
-! CHECK:           fir.do_concurrent
-! CHECK:             fir.do_concurrent.loop
-
-! Default lowering: nested loop carries the DO variable as an iter_arg and the
-! post-loop value is the loop result.
-! DEFAULT:           %[[RES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
-! DEFAULT:           fir.store %[[RES]] to %[[J_DECL]]#0 : !fir.ref<i32>
-
-! Clean lowering: nested loop has no iter_arg and the body recomputes the DO
-! variable from the induction variable; the post-loop value is computed as
-! lb + tripCount*step after the loop and stored to the DO variable.
-! CLEAN:             fir.do_loop %{{.*}} = %[[LB:[^ ]+]] to %[[UB:[^ ]+]] step %[[ST:[^ ]+]] {
-! CLEAN-NOT:           iter_args
-! CLEAN:               %[[IV:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CLEAN:               fir.store %[[IV]] to %[[J_DECL]]#0 : !fir.ref<i32>
-! CLEAN:             }
-! CLEAN:             %[[LBI:.*]] = fir.convert %[[LB]] : (index) -> i32
-! CLEAN:             %[[UBI:.*]] = fir.convert %[[UB]] : (index) -> i32
-! CLEAN:             %[[STI:.*]] = fir.convert %[[ST]] : (index) -> i32
-! CLEAN:             %[[C0:.*]] = arith.constant 0 : i32
-! CLEAN:             %[[DIFF:.*]] = arith.subi %[[UBI]], %[[LBI]] overflow<nsw> : i32
-! CLEAN:             %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STI]] overflow<nsw> : i32
-! CLEAN:             %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STI]] : i32
-! CLEAN:             %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CLEAN:             %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CLEAN:             %[[MUL:.*]] = arith.muli %[[SEL]], %[[STI]] overflow<nsw> : i32
-! CLEAN:             %[[LAST:.*]] = arith.addi %[[LBI]], %[[MUL]] overflow<nsw> : i32
-! CLEAN:             fir.store %[[LAST]] to %[[J_DECL]]#0 : !fir.ref<i32>
-
-! Non-unit lower bound and step: the post-loop value must still be lb +
-! tripCount*step (here 2 + 4*2 = 10), not a hard-coded lb=1/step=1 form.
-subroutine nested_stride(a, n)
-  implicit none
-  integer :: n, i, j
-  integer :: a(n)
-  do concurrent (i=1:n)
-    do j = 2, 8, 2
-    end do
-    a(i) = j
-  end do
-end subroutine
-
-! CHECK-LABEL:   func.func @_QPnested_stride
-! CHECK:           %[[SJ_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnested_strideEj"}
-! DEFAULT:           %[[SRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
-! DEFAULT:           fir.store %[[SRES]] to %[[SJ_DECL]]#0 : !fir.ref<i32>
-! CLEAN:             fir.do_loop %{{.*}} = %[[SLB:[^ ]+]] to %[[SUB:[^ ]+]] step %[[SST:[^ ]+]] {
-! CLEAN-NOT:           iter_args
-! CLEAN:             }
-! CLEAN:             %[[SLBI:.*]] = fir.convert %[[SLB]] : (index) -> i32
-! CLEAN:             %[[SUBI:.*]] = fir.convert %[[SUB]] : (index) -> i32
-! CLEAN:             %[[SSTI:.*]] = fir.convert %[[SST]] : (index) -> i32
-! CLEAN:             %[[SC0:.*]] = arith.constant 0 : i32
-! CLEAN:             %[[SDIFF:.*]] = arith.subi %[[SUBI]], %[[SLBI]] overflow<nsw> : i32
-! CLEAN:             %[[SADD:.*]] = arith.addi %[[SDIFF]], %[[SSTI]] overflow<nsw> : i32
-! CLEAN:             %[[STRIP:.*]] = arith.divsi %[[SADD]], %[[SSTI]] : i32
-! CLEAN:             %[[SCMP:.*]] = arith.cmpi slt, %[[STRIP]], %[[SC0]] : i32
-! CLEAN:             %[[SSEL:.*]] = arith.select %[[SCMP]], %[[SC0]], %[[STRIP]] : i32
-! CLEAN:             %[[SMUL:.*]] = arith.muli %[[SSEL]], %[[SSTI]] overflow<nsw> : i32
-! CLEAN:             %[[SLAST:.*]] = arith.addi %[[SLBI]], %[[SMUL]] overflow<nsw> : i32
-! CLEAN:             fir.store %[[SLAST]] to %[[SJ_DECL]]#0 : !fir.ref<i32>
-
-! Descending loop (step < 0): the same lb + tripCount*step formula must hold
-! (here 8 + 4*(-2) = 0).
-subroutine nested_stride_neg(a, n)
-  implicit none
-  integer :: n, i, j
-  integer :: a(n)
-  do concurrent (i=1:n)
-    do j = 8, 2, -2
-    end do
-    a(i) = j
-  end do
-end subroutine
-
-! CHECK-LABEL:   func.func @_QPnested_stride_neg
-! CHECK:           %[[NJ_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFnested_stride_negEj"}
-! DEFAULT:           %[[NRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
-! DEFAULT:           fir.store %[[NRES]] to %[[NJ_DECL]]#0 : !fir.ref<i32>
-! CLEAN:             fir.do_loop %{{.*}} = %[[NLB:[^ ]+]] to %[[NUB:[^ ]+]] step %[[NST:[^ ]+]] {
-! CLEAN-NOT:           iter_args
-! CLEAN:             }
-! CLEAN:             %[[NLBI:.*]] = fir.convert %[[NLB]] : (index) -> i32
-! CLEAN:             %[[NUBI:.*]] = fir.convert %[[NUB]] : (index) -> i32
-! CLEAN:             %[[NSTI:.*]] = fir.convert %[[NST]] : (index) -> i32
-! CLEAN:             %[[NC0:.*]] = arith.constant 0 : i32
-! CLEAN:             %[[NDIFF:.*]] = arith.subi %[[NUBI]], %[[NLBI]] overflow<nsw> : i32
-! CLEAN:             %[[NADD:.*]] = arith.addi %[[NDIFF]], %[[NSTI]] overflow<nsw> : i32
-! CLEAN:             %[[NTRIP:.*]] = arith.divsi %[[NADD]], %[[NSTI]] : i32
-! CLEAN:             %[[NCMP:.*]] = arith.cmpi slt, %[[NTRIP]], %[[NC0]] : i32
-! CLEAN:             %[[NSEL:.*]] = arith.select %[[NCMP]], %[[NC0]], %[[NTRIP]] : i32
-! CLEAN:             %[[NMUL:.*]] = arith.muli %[[NSEL]], %[[NSTI]] overflow<nsw> : i32
-! CLEAN:             %[[NLAST:.*]] = arith.addi %[[NLBI]], %[[NMUL]] overflow<nsw> : i32
-! CLEAN:             fir.store %[[NLAST]] to %[[NJ_DECL]]#0 : !fir.ref<i32>
-
-! A DO CONCURRENT with multiple induction variables is lowered as a single
-! fir.do_concurrent.loop carrying all the IVs (unaffected by the option); only
-! the nested plain DO loop is cleaned.
-subroutine multi_iv(a, n, m)
-  implicit none
-  integer :: n, m, i, j, k
-  integer :: a(n, m)
-  do concurrent (i=1:n, j=1:m)
-    do k = 1, 3
-      a(i, j) = a(i, j) + k
-    end do
-  end do
-end subroutine
-
-! CHECK-LABEL:   func.func @_QPmulti_iv
-! CHECK:           %[[MK_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFmulti_ivEk"}
-! CHECK:           fir.do_concurrent.loop (%{{[^)]*}}, %{{[^)]*}}) = (%{{[^)]*}}, %{{[^)]*}}) to (%{{[^)]*}}, %{{[^)]*}}) step (%{{[^)]*}}, %{{[^)]*}}) {
-! DEFAULT:           %[[MRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
-! DEFAULT:           fir.store %[[MRES]] to %[[MK_DECL]]#0 : !fir.ref<i32>
-! CLEAN:             fir.do_loop %{{.*}} = %[[MLB:[^ ]+]] to %[[MUB:[^ ]+]] step %[[MST:[^ ]+]] {
-! CLEAN-NOT:           iter_args
-! CLEAN:             }
-! CLEAN:             %[[MLBI:.*]] = fir.convert %[[MLB]] : (index) -> i32
-! CLEAN:             %[[MUBI:.*]] = fir.convert %[[MUB]] : (index) -> i32
-! CLEAN:             %[[MSTI:.*]] = fir.convert %[[MST]] : (index) -> i32
-! CLEAN:             %[[MC0:.*]] = arith.constant 0 : i32
-! CLEAN:             %[[MDIFF:.*]] = arith.subi %[[MUBI]], %[[MLBI]] overflow<nsw> : i32
-! CLEAN:             %[[MADD:.*]] = arith.addi %[[MDIFF]], %[[MSTI]] overflow<nsw> : i32
-! CLEAN:             %[[MTRIP:.*]] = arith.divsi %[[MADD]], %[[MSTI]] : i32
-! CLEAN:             %[[MCMP:.*]] = arith.cmpi slt, %[[MTRIP]], %[[MC0]] : i32
-! CLEAN:             %[[MSEL:.*]] = arith.select %[[MCMP]], %[[MC0]], %[[MTRIP]] : i32
-! CLEAN:             %[[MMUL:.*]] = arith.muli %[[MSEL]], %[[MSTI]] overflow<nsw> : i32
-! CLEAN:             %[[MLAST:.*]] = arith.addi %[[MLBI]], %[[MMUL]] overflow<nsw> : i32
-! CLEAN:             fir.store %[[MLAST]] to %[[MK_DECL]]#0 : !fir.ref<i32>
-
-! A DO CONCURRENT nested inside one of the cleaned plain DO loops is still
-! lowered as its own fir.do_concurrent.loop; the enclosing plain DO stays clean
-! and its post-loop value is materialized.
-subroutine dc_in_clean_loop(a, n, m)
-  implicit none
-  integer :: n, m, i, j, k
-  integer :: a(n)
-  do concurrent (i=1:n)
-    do j = 1, 3
-      do concurrent (k=1:m)
-        a(i) = a(i) + j*k
-      end do
-    end do
-  end do
-end subroutine
-
-! CHECK-LABEL:   func.func @_QPdc_in_clean_loop
-! CHECK:           %[[DJ_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFdc_in_clean_loopEj"}
-! CHECK:           fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
-! DEFAULT:           %[[DJRES:.*]] = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
-! DEFAULT:           fir.store %[[DJRES]] to %[[DJ_DECL]]#0 : !fir.ref<i32>
-! CLEAN:             fir.do_loop %{{.*}} = %{{[^ ]+}} to %{{[^ ]+}} step %{{[^ ]+}} {
-! CLEAN:               fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
-! CLEAN:             %{{.*}} = arith.divsi %{{.*}}, %{{.*}} : i32
-! CLEAN:             fir.store %{{.*}} to %[[DJ_DECL]]#0 : !fir.ref<i32>
-
-! Plain DO loops inside a DO CONCURRENT that is itself nested in the body are
-! cleaned at any depth.
-subroutine loop_in_nested_dc(a, n, m, p)
-  implicit none
-  integer :: n, m, p, i, j, k, l
-  integer :: a(n)
-  do concurrent (i=1:n)
-    do j = 1, 3
-      do concurrent (k=1:m)
-        do l = 1, 4
-          a(i) = a(i) + j*k*l
-        end do
-      end do
-    end do
-  end do
-end subroutine
-
-! CHECK-LABEL:   func.func @_QPloop_in_nested_dc
-! CHECK:           fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
-! DEFAULT:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
-! DEFAULT:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
-! CLEAN:             fir.do_loop %{{.*}} = %{{[^ ]+}} to %{{[^ ]+}} step %{{[^ ]+}} {
-! CLEAN:               fir.do_concurrent.loop (%{{[^)]*}}) = (%{{[^)]*}}) to (%{{[^)]*}}) step (%{{[^)]*}}) {
-! CLEAN:                 fir.do_loop %{{.*}} = %{{[^ ]+}} to %{{[^ ]+}} step %{{[^ ]+}} {
-
-! A plain DO loop not nested in a DO CONCURRENT body keeps its iter_arg even
-! when the option is enabled.
-subroutine not_nested(x)
-  implicit none
-  integer :: x, j
-  do j = 1, 3
-  end do
-  x = j
-end subroutine
-
-! CHECK-LABEL:   func.func @_QPnot_nested
-! CLEAN:           fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (i32) {
diff --git a/flang/test/Lower/do_concurrent_loop_in_nested_block.f90 b/flang/test/Lower/do_concurrent_loop_in_nested_block.f90
index 79bde5eed7817..f498c01f3d140 100644
--- a/flang/test/Lower/do_concurrent_loop_in_nested_block.f90
+++ b/flang/test/Lower/do_concurrent_loop_in_nested_block.f90
@@ -17,8 +17,9 @@ subroutine loop_in_nested_block
 ! CHECK:         fir.do_concurrent {
 ! CHECK:           fir.do_concurrent.loop {{.*}} local(@{{.*}} %[[OUTER_J_DECL]]#0 -> %[[LOCAL_J_ARG:.*]] : !fir.ref<i32>) {
 ! CHECK:             %[[LOCAL_J_DECL:.*]]:2 = hlfir.declare %[[LOCAL_J_ARG]]
-! CHECK:             fir.do_loop {{.*}} iter_args(%[[NESTED_LOOP_ARG:.*]] = {{.*}}) {
-! CHECK:               fir.store %[[NESTED_LOOP_ARG]] to %[[LOCAL_J_DECL]]#0
+! CHECK:             fir.do_loop %[[NESTED_IV:.*]] = {{.*}} to {{.*}} step {{.*}} {
+! CHECK:               %[[NESTED_J:.*]] = fir.convert %[[NESTED_IV]] : (index) -> i32
+! CHECK:               fir.store %[[NESTED_J]] to %[[LOCAL_J_DECL]]#0
 ! CHECK:             }
 ! CHECK:           }
 ! CHECK:         }
diff --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90
index b98a0e7108113..91be10a7d076d 100644
--- a/flang/test/Lower/do_loop.f90
+++ b/flang/test/Lower/do_loop.f90
@@ -2,8 +2,9 @@
 ! RUN: %flang_fc1 -emit-hlfir -fwrapv -o - %s | FileCheck %s --check-prefix=NO-NSW
 
 ! Simple tests for structured ordered loops with loop-control.
-! Tests the structure of the loop, storage to index variable and return and
-! storage of the final value of the index variable.
+! The DO variable is recomputed from the induction variable inside the loop
+! body (no secondary-induction iter_arg), and its Fortran post-loop value is
+! materialized after the loop.
 
 ! NO-NSW-NOT: overflow<nsw>
 
@@ -19,19 +20,24 @@ subroutine simple_loop
   ! CHECK: %[[C5:.*]] = arith.constant 5 : i32
   ! CHECK: %[[C5_CVT:.*]] = fir.convert %[[C5]] : (i32) -> index
   ! CHECK: %[[C1_STEP:.*]] = arith.constant 1 : index
-  ! CHECK: %[[LB:.*]] = fir.convert %[[C1_CVT]] : (index) -> i32
-  ! CHECK: %[[LI_RES:.*]] = fir.do_loop %[[LI:[^ ]*]] =
-  ! CHECK-SAME: %[[C1_CVT]] to %[[C5_CVT]] step %[[C1_STEP]]
-  ! CHECK-SAME: iter_args(%[[IV:.*]] = %[[LB]]) -> (i32) {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[C1_CVT]] to %[[C5_CVT]] step %[[C1_STEP]] {
   do i=1,5
+  ! CHECK:   %[[IV:.*]] = fir.convert %[[LI]] : (index) -> i32
   ! CHECK:   fir.store %[[IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
-  ! CHECK:   %[[STEPCAST:.*]] = fir.convert %[[C1_STEP]] : (index) -> i32
-  ! CHECK:   %[[IVLOAD:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
-  ! CHECK:   %[[IVINC:.*]] = arith.addi %[[IVLOAD]], %[[STEPCAST]] overflow<nsw> : i32
-  ! CHECK:  fir.result %[[IVINC]] : i32
   ! CHECK: }
   end do
-  ! CHECK: fir.store %[[LI_RES]] to %[[I_DECL]]#0 : !fir.ref<i32>
+  ! CHECK: %[[LB:.*]] = fir.convert %[[C1_CVT]] : (index) -> i32
+  ! CHECK: %[[UB:.*]] = fir.convert %[[C5_CVT]] : (index) -> i32
+  ! CHECK: %[[STEP:.*]] = fir.convert %[[C1_STEP]] : (index) -> i32
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+  ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: %[[I:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: %{{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[I]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
   print *, i
@@ -56,22 +62,18 @@ subroutine nested_loop
   ! CHECK: %[[E_I:.*]] = arith.constant 5 : i32
   ! CHECK: %[[E_I_CVT:.*]] = fir.convert %[[E_I]] : (i32) -> index
   ! CHECK: %[[ST_I:.*]] = arith.constant 1 : index
-  ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_I_CVT]] : (index) -> i32
-  ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:[^ ]*]] =
-  ! CHECK-SAME: %[[S_I_CVT]] to %[[E_I_CVT]] step %[[ST_I]]
-  ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (i32) {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S_I_CVT]] to %[[E_I_CVT]] step %[[ST_I]] {
   do i=1,5
+    ! CHECK: %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
     ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
     ! CHECK: %[[S_J:.*]] = arith.constant 1 : i32
     ! CHECK: %[[S_J_CVT:.*]] = fir.convert %[[S_J]] : (i32) -> index
     ! CHECK: %[[E_J:.*]] = arith.constant 5 : i32
     ! CHECK: %[[E_J_CVT:.*]] = fir.convert %[[E_J]] : (i32) -> index
     ! CHECK: %[[ST_J:.*]] = arith.constant 1 : index
-    ! CHECK: %[[J_LB:.*]] = fir.convert %[[S_J_CVT]] : (index) -> i32
-    ! CHECK: %[[J_RES:.*]] = fir.do_loop %[[LJ:[^ ]*]] =
-    ! CHECK-SAME: %[[S_J_CVT]] to %[[E_J_CVT]] step %[[ST_J]]
-    ! CHECK-SAME: iter_args(%[[J_IV:.*]] = %[[J_LB]]) -> (i32) {
+    ! CHECK: fir.do_loop %[[LJ:[^ ]*]] = %[[S_J_CVT]] to %[[E_J_CVT]] step %[[ST_J]] {
     do j=1,5
+      ! CHECK: %[[J_IV:.*]] = fir.convert %[[LJ]] : (index) -> i32
       ! CHECK: fir.store %[[J_IV]] to %[[J_DECL]]#0 : !fir.ref<i32>
       ! CHECK: %[[ASUM:.*]] = fir.load %[[ASUM_DECL]]#0 : !fir.ref<i32>
       ! CHECK: %[[I:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
@@ -83,20 +85,34 @@ subroutine nested_loop
       ! CHECK: %[[ASUM_NEW:.*]] = arith.addi %[[ASUM]], %[[ARR_VAL]] : i32
       ! CHECK: hlfir.assign %[[ASUM_NEW]] to %[[ASUM_DECL]]#0 : i32, !fir.ref<i32>
       asum = asum + arr(i,j)
-      ! CHECK: %[[J_STEPCAST:.*]] = fir.convert %[[ST_J]] : (index) -> i32
-      ! CHECK: %[[J_IVLOAD:.*]] = fir.load %[[J_DECL]]#0 : !fir.ref<i32>
-      ! CHECK: %[[J_IVINC:.*]] = arith.addi %[[J_IVLOAD]], %[[J_STEPCAST]] overflow<nsw> : i32
-      ! CHECK: fir.result %[[J_IVINC]] : i32
     ! CHECK: }
     end do
-    ! CHECK: fir.store %[[J_RES]] to %[[J_DECL]]#0 : !fir.ref<i32>
-    ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[ST_I]] : (index) -> i32
-    ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
-    ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] overflow<nsw> : i32
-    ! CHECK: fir.result %[[I_IVINC]] : i32
+    ! CHECK: %[[J_LB:.*]] = fir.convert %[[S_J_CVT]] : (index) -> i32
+    ! CHECK: %[[J_UB:.*]] = fir.convert %[[E_J_CVT]] : (index) -> i32
+    ! CHECK: %[[J_STEP:.*]] = fir.convert %[[ST_J]] : (index) -> i32
+    ! CHECK: %[[J_C0:.*]] = arith.constant 0 : i32
+    ! CHECK: %[[J_DIFF:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
+    ! CHECK: %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[J_STEP]] overflow<nsw> : i32
+    ! CHECK: %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[J_STEP]] : i32
+    ! CHECK: %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : i32
+    ! CHECK: %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : i32
+    ! CHECK: %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[J_STEP]] overflow<nsw> : i32
+    ! CHECK: %[[J_LAST:.*]] = arith.addi %[[J_LB]], %[[J_MUL]] overflow<nsw> : i32
+    ! CHECK: fir.store %[[J_LAST]] to %[[J_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
-  ! CHECK: fir.store %[[I_RES]] to %[[I_DECL]]#0 : !fir.ref<i32>
+  ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_I_CVT]] : (index) -> i32
+  ! CHECK: %[[I_UB:.*]] = fir.convert %[[E_I_CVT]] : (index) -> i32
+  ! CHECK: %[[I_STEP:.*]] = fir.convert %[[ST_I]] : (index) -> i32
+  ! CHECK: %[[I_C0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[I_DIFF:.*]] = arith.subi %[[I_UB]], %[[I_LB]] overflow<nsw> : i32
+  ! CHECK: %[[I_ADD:.*]] = arith.addi %[[I_DIFF]], %[[I_STEP]] overflow<nsw> : i32
+  ! CHECK: %[[I_TRIP:.*]] = arith.divsi %[[I_ADD]], %[[I_STEP]] : i32
+  ! CHECK: %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TRIP]], %[[I_C0]] : i32
+  ! CHECK: %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TRIP]] : i32
+  ! CHECK: %[[I_MUL:.*]] = arith.muli %[[I_SEL]], %[[I_STEP]] overflow<nsw> : i32
+  ! CHECK: %[[I_LAST:.*]] = arith.addi %[[I_LB]], %[[I_MUL]] overflow<nsw> : i32
+  ! CHECK: fir.store %[[I_LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
 end subroutine
 
 ! Test a downcounting loop
@@ -112,19 +128,24 @@ subroutine down_counting_loop()
   ! CHECK: %[[C1_CVT:.*]] = fir.convert %[[C1]] : (i32) -> index
   ! CHECK: %[[CMINUS1:.*]] = arith.constant -1 : i32
   ! CHECK: %[[CMINUS1_STEP_CVT:.*]] = fir.convert %[[CMINUS1]] : (i32) -> index
-  ! CHECK: %[[I_LB:.*]] = fir.convert %[[C5_CVT]] : (index) -> i32
-  ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:[^ ]*]] =
-  ! CHECK-SAME: %[[C5_CVT]] to %[[C1_CVT]] step %[[CMINUS1_STEP_CVT]]
-  ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (i32) {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[C5_CVT]] to %[[C1_CVT]] step %[[CMINUS1_STEP_CVT]] {
   do i=5,1,-1
+  ! CHECK: %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
   ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
-  ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[CMINUS1_STEP_CVT]] : (index) -> i32
-  ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
-  ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] overflow<nsw> : i32
-  ! CHECK: fir.result %[[I_IVINC]] : i32
   ! CHECK: }
   end do
-  ! CHECK: fir.store %[[I_RES]] to %[[I_DECL]]#0 : !fir.ref<i32>
+  ! CHECK: %[[LB:.*]] = fir.convert %[[C5_CVT]] : (index) -> i32
+  ! CHECK: %[[UB:.*]] = fir.convert %[[C1_CVT]] : (index) -> i32
+  ! CHECK: %[[STEP:.*]] = fir.convert %[[CMINUS1_STEP_CVT]] : (index) -> i32
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+  ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
 end subroutine
 
 ! Test a general loop with a variable step
@@ -143,19 +164,24 @@ subroutine loop_with_variable_step(s,e,st)
   ! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i32) -> index
   ! CHECK: %[[ST:.*]] = fir.load %[[ST_DECL]]#0 : !fir.ref<i32>
   ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index
-  ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32
-  ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:[^ ]*]] =
-  ! CHECK-SAME: %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]]
-  ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (i32) {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] {
   do i=s,e,st
+  ! CHECK:  %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
   ! CHECK:  fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
-  ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32
-  ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
-  ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] overflow<nsw> : i32
-  ! CHECK:  fir.result %[[I_IVINC]] : i32
   ! CHECK: }
   end do
-  ! CHECK: fir.store %[[I_RES]] to %[[I_DECL]]#0 : !fir.ref<i32>
+  ! CHECK: %[[LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32
+  ! CHECK: %[[UB:.*]] = fir.convert %[[E_CVT]] : (index) -> i32
+  ! CHECK: %[[STEP:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+  ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
 end subroutine
 
 ! Test usage of pointer variables as index, start, end and step variables
@@ -197,19 +223,24 @@ subroutine loop_with_pointer_variables(s,e,st)
 ! CHECK:  %[[ST_PTR:.*]] = fir.box_addr %[[ST_BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
 ! CHECK:  %[[ST:.*]] = fir.load %[[ST_PTR]] : !fir.ptr<i32>
 ! CHECK:  %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index
-! CHECK:  %[[I_LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32
-! CHECK:  %[[I_RES:.*]] = fir.do_loop %[[LI:[^ ]*]] =
-! CHECK-SAME: %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]]
-! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (i32) {
+! CHECK:  fir.do_loop %[[LI:[^ ]*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] {
   do iptr=sptr,eptr,stptr
+! CHECK:    %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
 ! CHECK:    fir.store %[[I_IV]] to %[[I_PTR]] : !fir.ptr<i32>
-! CHECK:    %[[I_STEPCAST:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32
-! CHECK:    %[[I_IVLOAD:.*]] = fir.load %[[I_PTR]] : !fir.ptr<i32>
-! CHECK:    %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] overflow<nsw> : i32
-! CHECK:    fir.result %[[I_IVINC]] : i32
-  end do
 ! CHECK:  }
-! CHECK:  fir.store %[[I_RES]] to %[[I_PTR]] : !fir.ptr<i32>
+  end do
+! CHECK:  %[[LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32
+! CHECK:  %[[UB:.*]] = fir.convert %[[E_CVT]] : (index) -> i32
+! CHECK:  %[[STEP:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32
+! CHECK:  %[[C0:.*]] = arith.constant 0 : i32
+! CHECK:  %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+! CHECK:  %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+! CHECK:  %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+! CHECK:  %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CHECK:  %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CHECK:  %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+! CHECK:  %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:  fir.store %[[LAST]] to %[[I_PTR]] : !fir.ptr<i32>
 end subroutine
 
 ! Test usage of non-default integer kind for loop control and loop index variable
@@ -230,19 +261,24 @@ subroutine loop_with_non_default_integer(s,e,st)
   ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i64) -> index
   integer(kind=8) :: s, e, st
 
-  ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i64
-  ! CHECK: %[[I_RES:.*]] = fir.do_loop %[[LI:[^ ]*]] =
-  ! CHECK-SAME: %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]]
-  ! CHECK-SAME: iter_args(%[[I_IV:.*]] = %[[I_LB]]) -> (i64) {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] {
   do i=s,e,st
+    ! CHECK: %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i64
     ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i64>
-    ! CHECK: %[[I_STEPCAST:.*]] = fir.convert %[[ST_CVT]] : (index) -> i64
-    ! CHECK: %[[I_IVLOAD:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i64>
-    ! CHECK: %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], %[[I_STEPCAST]] overflow<nsw> : i64
-    ! CHECK: fir.result %[[I_IVINC]] : i64
-  end do
   ! CHECK: }
-  ! CHECK: fir.store %[[I_RES]] to %[[I_DECL]]#0 : !fir.ref<i64>
+  end do
+  ! CHECK: %[[LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i64
+  ! CHECK: %[[UB:.*]] = fir.convert %[[E_CVT]] : (index) -> i64
+  ! CHECK: %[[STEP:.*]] = fir.convert %[[ST_CVT]] : (index) -> i64
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : i64
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i64
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i64
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i64
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i64
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i64
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i64
+  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i64
+  ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i64>
 end subroutine
 
 ! Test real loop control.
diff --git a/flang/test/Lower/do_loop_unstructured.f90 b/flang/test/Lower/do_loop_unstructured.f90
index 99b8cddd083fa..5448647dbf27f 100644
--- a/flang/test/Lower/do_loop_unstructured.f90
+++ b/flang/test/Lower/do_loop_unstructured.f90
@@ -169,13 +169,23 @@ subroutine nested_structured_in_unstructured()
 ! CHECK:   %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
 ! CHECK:   cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
 ! CHECK: ^[[BODY]]:
-! CHECK:   %{{.*}} = fir.do_loop %[[J_INDEX:[^ ]*]] =
-! CHECK-SAME: %{{.*}} to %{{.*}} step %[[ST:[^ ]*]]
-! CHECK-SAME: iter_args(%[[J_IV:.*]] = %{{.*}}) -> (i32) {
+! CHECK:   fir.do_loop %[[J_INDEX:[^ ]*]] =
+! CHECK-SAME: %{{.*}} to %{{.*}} step %[[ST:[^ ]*]] {
+! CHECK:     %[[J_IV:.*]] = fir.convert %[[J_INDEX]] : (index) -> i32
 ! CHECK:     fir.store %[[J_IV]] to %[[LOOP_VAR_J_DECL]]#0 : !fir.ref<i32>
-! CHECK:     %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_DECL]]#0 : !fir.ref<i32>
-! CHECK:     %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %{{[^ ]*}} overflow<nsw> : i32
 ! CHECK:   }
+! CHECK:   %[[J_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:   %[[J_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:   %[[J_STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK:   %[[J_C0:.*]] = arith.constant 0 : i32
+! CHECK:   %[[J_DIFF:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
+! CHECK:   %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[J_STEP]] overflow<nsw> : i32
+! CHECK:   %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[J_STEP]] : i32
+! CHECK:   %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : i32
+! CHECK:   %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : i32
+! CHECK:   %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[J_STEP]] overflow<nsw> : i32
+! CHECK:   %[[J_LAST:.*]] = arith.addi %[[J_LB]], %[[J_MUL]] overflow<nsw> : i32
+! CHECK:   fir.store %[[J_LAST]] to %[[LOOP_VAR_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
 ! CHECK:   %[[C1_3:.*]] = arith.constant 1 : i32
 ! CHECK:   %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[C1_3]] : i32
diff --git a/flang/test/Lower/infinite_loop.f90 b/flang/test/Lower/infinite_loop.f90
index 64fe0bc1b965a..c5f2196ff01be 100644
--- a/flang/test/Lower/infinite_loop.f90
+++ b/flang/test/Lower/infinite_loop.f90
@@ -96,17 +96,22 @@ subroutine structured_loop_in_infinite(i)
 ! CHECK: ^[[BODY2:.*]]:
 ! CHECK:  %[[C1_INDEX:.*]] = fir.convert %[[C1]] : (i32) -> index
 ! CHECK:  %[[C10_INDEX:.*]] = fir.convert %[[C10]] : (i32) -> index
-! CHECK:  %[[J_LB:.*]] = fir.convert %[[C1_INDEX]] : (index) -> i32
-! CHECK:  %[[J_FINAL:.*]] = fir.do_loop %[[J:[^ ]*]] =
-! CHECK-SAME: %[[C1_INDEX]] to %[[C10_INDEX]] step %[[C1_1]]
-! CHECK-SAME: iter_args(%[[J_IV:.*]] = %[[J_LB]]) -> (i32) {
+! CHECK:  fir.do_loop %[[J:[^ ]*]] =
+! CHECK-SAME: %[[C1_INDEX]] to %[[C10_INDEX]] step %[[C1_1]] {
+! CHECK:    %[[J_IV:.*]] = fir.convert %[[J]] : (index) -> i32
 ! CHECK:    fir.store %[[J_IV]] to %[[J_DECL]] : !fir.ref<i32>
-! CHECK:    %[[J_STEPCAST:.*]] = fir.convert %[[C1_1]] : (index) -> i32
-! CHECK:    %[[J_IVLOAD:.*]] = fir.load %[[J_DECL]] : !fir.ref<i32>
-! CHECK:    %[[J_IVINC:.*]] = arith.addi %[[J_IVLOAD]], %[[J_STEPCAST]] overflow<nsw> : i32
-! CHECK:    fir.result %[[J_IVINC]] : i32
 ! CHECK:  }
-! CHECK:  fir.store %[[J_FINAL]] to %[[J_DECL]] : !fir.ref<i32>
+! CHECK:  %[[J_LB:.*]] = fir.convert %[[C1_INDEX]] : (index) -> i32
+! CHECK:  %[[J_UB:.*]] = fir.convert %[[C10_INDEX]] : (index) -> i32
+! CHECK:  %[[J_STEP:.*]] = fir.convert %[[C1_1]] : (index) -> i32
+! CHECK:  %[[J_DIFF:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
+! CHECK:  %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[J_STEP]] overflow<nsw> : i32
+! CHECK:  %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[J_STEP]] : i32
+! CHECK:  %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %{{.*}} : i32
+! CHECK:  %[[J_SEL:.*]] = arith.select %[[J_CMP]], %{{.*}}, %[[J_TRIP]] : i32
+! CHECK:  %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[J_STEP]] overflow<nsw> : i32
+! CHECK:  %[[J_LAST:.*]] = arith.addi %[[J_LB]], %[[J_MUL]] overflow<nsw> : i32
+! CHECK:  fir.store %[[J_LAST]] to %[[J_DECL]] : !fir.ref<i32>
 ! CHECK:  cf.br ^[[BODY1]]
 ! CHECK: ^[[RETURN]]:
 ! CHECK:   return
diff --git a/flang/test/Lower/inline_directive.f90 b/flang/test/Lower/inline_directive.f90
index 5748690d5914d..d77b170780f53 100644
--- a/flang/test/Lower/inline_directive.f90
+++ b/flang/test/Lower/inline_directive.f90
@@ -36,14 +36,14 @@ subroutine test_inline()
 
   !dir$ forceinline
   do i = 1, 100
-    !CHECK: fir.do_loop %[[ARG_0:.*]] = %[[FROM:.*]] to %[[TO:.*]] step %[[C1:.*]]  iter_args(%[[ARG_1:.*]] = {{.*}}) -> (i32) {
+    !CHECK: fir.do_loop %[[ARG_0:.*]] = %[[FROM:.*]] to %[[TO:.*]] step %[[C1:.*]] {
     !CHECK:  fir.call @_QFtest_inlinePf(%[[VAL_1]], %[[VAL_3]]) fastmath<contract> {inline_attr = #fir.inline_attrs<always_inline>} : (!fir.ref<i32>, !fir.ref<i32>) -> ()
     call f(x, y)
   enddo
 
   !dir$ inline
   do i = 1, 100
-    !CHECK: fir.do_loop %[[ARG_0:.*]] = %[[FROM:.*]] to %[[TO:.*]] step %[[C1:.*]]  iter_args(%[[ARG_1:.*]] = {{.*}}) -> (i32) {
+    !CHECK: fir.do_loop %[[ARG_0:.*]] = %[[FROM:.*]] to %[[TO:.*]] step %[[C1:.*]] {
     !CHECK:  fir.call @_QFtest_inlinePf(%[[VAL_1]], %[[VAL_3]]) fastmath<contract> {inline_attr = #fir.inline_attrs<inline_hint>} : (!fir.ref<i32>, !fir.ref<i32>) -> ()
     call f(x, y)
   enddo
diff --git a/flang/test/Lower/ivdep.f90 b/flang/test/Lower/ivdep.f90
index 69f54cd1b0604..d1ea01425b635 100644
--- a/flang/test/Lower/ivdep.f90
+++ b/flang/test/Lower/ivdep.f90
@@ -23,10 +23,6 @@ subroutine ivdep_test1
      !CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> i64
      !CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_2:.*]]#0 (%[[VAL_11]])  : (!fir.ref<!fir.array<10xi32>>, i64)
      !CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_12]] {access_groups = [#access_group]} : i32, !fir.ref<i32> 
-     !CHECK: %[[VAL_14:.*]] = fir.convert %[[C1:.*]] : (index) -> i32
-     !CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_4]]#0 {accessGroups = [#access_group]}
-     !CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[VAL_14]] overflow<nsw> : i32
-     !CHECK: fir.result %[[VAL_16]] : i32 
   end do     
 end subroutine ivdep_test1
 
@@ -53,10 +49,6 @@ subroutine ivdep_test2
      !CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> i64
      !CHECK: %[[VAL_26:.*]] = hlfir.designate %[[VAL_2:.*]]#0 (%[[VAL_25]])  : (!fir.ref<!fir.array<10xi32>>, i64)
      !CHECK: hlfir.assign %[[VAL_23]] to %[[VAL_26]] {access_groups = [#access_group1]} : i32, !fir.ref<i32> 
-     !CHECK: %[[VAL_28:.*]] = fir.convert %[[C1:.*]] : (index) -> i32
-     !CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group1]}
-     !CHECK: %[[VAL_30:.*]] = arith.addi %[[VAL_29]], %[[VAL_28]] overflow<nsw> : i32
-     !CHECK: fir.result %[[VAL_30]] : i32
   end do
 end subroutine ivdep_test2
 
@@ -84,10 +76,6 @@ subroutine ivdep_test3
      !CHECK: %[[VAL_26:.*]] = hlfir.designate %[[VAL_2:.*]]#0 (%[[VAL_25]])  : (!fir.ref<!fir.array<10xi32>>, i64)
      !CHECK: hlfir.assign %[[VAL_23]] to %[[VAL_26]] {access_groups = [#access_group2]} : i32, !fir.ref<i32>
      !CHECK: fir.call @_QFivdep_test3Pfoo() fastmath<contract> {accessGroups = [#access_group2]}
-     !CHECK: %[[VAL_28:.*]] = fir.convert %[[C1:.*]] : (index) -> i32
-     !CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_10]]#0 {accessGroups = [#access_group2]}
-     !CHECK: %[[VAL_30:.*]] = arith.addi %[[VAL_29]], %[[VAL_28]] overflow<nsw> : i32
-     !CHECK: fir.result %[[VAL_30]] : i32 
   end do
   contains
     subroutine foo()
diff --git a/flang/test/Lower/loops.f90 b/flang/test/Lower/loops.f90
index bb66f79d5564a..7c500b7a85199 100644
--- a/flang/test/Lower/loops.f90
+++ b/flang/test/Lower/loops.f90
@@ -31,7 +31,7 @@ subroutine loop_test
     a(i,j,k) = a(i,j,k) + 1
   enddo
 
-  ! CHECK-COUNT-3: fir.do_loop {{[^un]*}} -> (i32)
+  ! CHECK-COUNT-3: fir.do_loop {{[^un]*}}
   asum = 0
   do i=1,5
     do j=1,5
@@ -118,7 +118,7 @@ subroutine lis(n)
   ! CHECK:           %[[V_P_ALLOC:[0-9]+]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x?x?xi32>>> {bindc_name = "p", pinned, uniq_name = "_QFlisEp"}
   ! CHECK:           fir.store %{{.*}} to %[[V_P_ALLOC]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x?xi32>>>>
   ! CHECK:           %[[V_P_DECL:.*]]:2 = hlfir.declare %[[V_P_ALLOC]]
-  ! CHECK:           fir.do_loop %arg3 = %{{.*}} to %{{.*}} step %c1{{.*}} iter_args(%arg4 = %{{.*}}) -> (i32) {
+  ! CHECK:           fir.do_loop %arg3 = %{{.*}} to %{{.*}} step %c1{{.*}} {
   ! CHECK:             fir.do_concurrent {
   ! CHECK:               fir.alloca i32 {bindc_name = "m"}
   ! CHECK:               fir.do_concurrent.loop (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) {
diff --git a/flang/test/Lower/loops2.f90 b/flang/test/Lower/loops2.f90
index b24e8b6401ce6..c925c210d737d 100644
--- a/flang/test/Lower/loops2.f90
+++ b/flang/test/Lower/loops2.f90
@@ -15,9 +15,21 @@ subroutine test_pointer()
 ! CHECK: %[[PTR:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMtest_loop_varEi_pointer"}
 ! CHECK: %[[BOX:.*]] = fir.load %[[PTR]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
 ! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
-! CHECK: %[[LOOP:.*]] = fir.do_loop
+! CHECK: fir.do_loop
 ! CHECK:   fir.store %{{.*}} to %[[ADDR]] : !fir.ptr<i32>
-! CHECK: fir.store %[[LOOP]] to %[[ADDR]] : !fir.ptr<i32>
+! CHECK: }
+! CHECK: %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK: %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK: %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK: fir.store %[[LAST]] to %[[ADDR]] : !fir.ptr<i32>
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMtest_loop_varPtest_allocatable
@@ -27,9 +39,21 @@ subroutine test_allocatable()
 ! CHECK: %[[ALLOC:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMtest_loop_varEi_allocatable"}
 ! CHECK: %[[BOX:.*]] = fir.load %[[ALLOC]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
 ! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
-! CHECK: %[[LOOP:.*]] = fir.do_loop
+! CHECK: fir.do_loop
 ! CHECK:   fir.store %{{.*}} to %[[ADDR]] : !fir.heap<i32>
-! CHECK: fir.store %[[LOOP]] to %[[ADDR]] : !fir.heap<i32>
+! CHECK: }
+! CHECK: %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK: %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK: %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK: fir.store %[[LAST]] to %[[ADDR]] : !fir.heap<i32>
   end subroutine
 
 ! CHECK-LABEL: func.func @_QMtest_loop_varPtest_real_pointer
diff --git a/flang/test/Lower/mixed_loops.f90 b/flang/test/Lower/mixed_loops.f90
index 2a5aa40ff22cd..4fa9f9bf6d289 100644
--- a/flang/test/Lower/mixed_loops.f90
+++ b/flang/test/Lower/mixed_loops.f90
@@ -74,19 +74,31 @@ subroutine do_inside_while_loop
     do while (j .lt. 21)
       ! CHECK: ^[[BODY1]]:  // pred: ^[[HDR1]]
 
-      ! 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>
-      ! CHECK:     %[[JINC:.*]] = arith.muli %[[C2]], %[[J2VAL]] : i32
-      ! CHECK:     hlfir.assign %[[JINC]] to %[[J]]#0 : i32, !fir.ref<i32>
-      ! CHECK:     %[[I_IVLOAD:.*]] = fir.load %[[I]]#0 : !fir.ref<i32>
-      ! CHECK:     %[[I_IVINC:.*]] = arith.addi %[[I_IVLOAD]], {{.*}} overflow<nsw> : i32
-      ! CHECK:     fir.result %[[I_IVINC]] : i32
+      ! 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 %[[LI:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+        ! CHECK: %[[IV:.*]] = fir.convert %[[LI]] : (index) -> i32
+        ! CHECK: fir.store %[[IV]] to %[[I]]#0 : !fir.ref<i32>
+        ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
+        ! CHECK: %[[J2VAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
+        ! CHECK: %[[JINC:.*]] = arith.muli %[[C2]], %[[J2VAL]] : i32
+        ! CHECK: hlfir.assign %[[JINC]] to %[[J]]#0 : i32, !fir.ref<i32>
       do i=8,13
         j=j*2
 
-      ! CHECK:   fir.store %{{.*}} to %[[I]]#0 : !fir.ref<i32>
+      ! CHECK: %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
+      ! CHECK: %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
+      ! CHECK: %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
+      ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+      ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
+      ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
+      ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
+      ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
+      ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
+      ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
+      ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+      ! CHECK: fir.store %[[LAST]] to %[[I]]#0 : !fir.ref<i32>
       end do
 
     ! CHECK:   cf.br ^[[HDR1]]
diff --git a/flang/test/Lower/nsw.f90 b/flang/test/Lower/nsw.f90
index 4bc932ac38508..5f216b830649c 100644
--- a/flang/test/Lower/nsw.f90
+++ b/flang/test/Lower/nsw.f90
@@ -83,8 +83,7 @@ subroutine loop_params(a,lb,ub,st)
 ! CHECK:           %[[VAL_29:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
 ! CHECK:           %[[VAL_30:.*]] = arith.muli %[[VAL_29]], %[[VAL_4]] overflow<nsw> : i32
 ! CHECK:           %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (i32) -> index
-! CHECK:           %[[VAL_32:.*]] = fir.convert %[[VAL_26]] : (index) -> i32
-! CHECK:           %[[VAL_33:.*]] = fir.do_loop %[[VAL_34:.*]] = %[[VAL_26]] to %[[VAL_28]] step %[[VAL_31]] iter_args(%[[VAL_35:.*]] = %[[VAL_32]]) -> (i32) {
+! CHECK:           fir.do_loop %[[VAL_34:.*]] = %[[VAL_26]] to %[[VAL_28]] step %[[VAL_31]] {
 
 subroutine loop_params2(a,lb,ub,st)
   integer :: i, lb, ub, st
diff --git a/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90 b/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90
index ebacd0353b90b..790bda5bb7d23 100644
--- a/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90
+++ b/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90
@@ -48,9 +48,10 @@ program main
 
 ! COMMON: omp.wsloop {
 ! COMMON: omp.loop_nest ({{[^[:space:]]+}}) {{.*}} {
-! COMMON:   fir.do_loop {{.*}} iter_args(%[[J_IV:.*]] = {{.*}}) -> {{.*}} {
-! HOST:       fir.store %[[J_IV]] to %[[ORIG_J_DECL]]#0
-! DEVICE:     fir.store %[[J_IV]] to %[[TARGET_J_DECL]]#0
+! COMMON:   fir.do_loop %[[J_IV:.*]] = {{.*}} to {{.*}} step {{.*}} {
+! COMMON:     %[[J_IV_CONV:.*]] = fir.convert %[[J_IV]] : (index) -> i32
+! HOST:       fir.store %[[J_IV_CONV]] to %[[ORIG_J_DECL]]#0
+! DEVICE:     fir.store %[[J_IV_CONV]] to %[[TARGET_J_DECL]]#0
 
 ! COMMON:     fir.do_concurrent {
 ! COMMON:         %[[ORIG_K_ALLOC:.*]] = fir.alloca i32 {bindc_name = "k"}
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 6d2a51c20d97a..e1017a0005b50 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -234,13 +234,6 @@ static llvm::cl::opt<bool> enableCUDAInit("fcuda-init",
                                           llvm::cl::desc("enable CUDA Init"),
                                           llvm::cl::init(false));
 
-static llvm::cl::opt<bool> doConcurrentCleanNestedLoops(
-    "fdo-concurrent-clean-nested-loops",
-    llvm::cl::desc(
-        "lower plain DO loops nested in DO CONCURRENT bodies without "
-        "the secondary-induction iter_arg"),
-    llvm::cl::init(false));
-
 static llvm::cl::opt<bool>
     enableDoConcurrentOffload("fdoconcurrent-offload",
                               llvm::cl::desc("enable do concurrent offload"),
@@ -513,7 +506,6 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
   loweringOptions.setRepackArrays(repackArrays);
   loweringOptions.setRepackArraysWhole(repackArraysWhole);
   loweringOptions.setSkipExternalRttiDefinition(skipExternalRttiDefinition);
-  loweringOptions.setDoConcurrentCleanNestedLoops(doConcurrentCleanNestedLoops);
   if (enableCUDA)
     loweringOptions.setCUDARuntimeCheck(true);
   if (complexRange == "improved" || complexRange == "basic")

>From 2093b54c87cb75a8dd6ef612593958c6c6b7edee Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Tue, 7 Jul 2026 18:13:39 -0700
Subject: [PATCH 10/12] [flang] Compute DO-loop post-loop value in index type

The materialized post-loop value computed the trip count in the DO variable's
type, which overflows for empty range-extreme loops (e.g. do i=huge(i),
-huge(i)-1) and yields a wrong final value. Compute it in the loop's index
type, matching how the loop counts iterations, then convert once.
---
 flang/lib/Lower/Bridge.cpp                    |  28 ++--
 .../Lower/OpenMP/hlfir-seqloop-parallel.f90   |  88 +++++------
 .../OpenMP/parallel-private-clause-fixes.f90  |  20 ++-
 .../OpenMP/sections-predetermined-private.f90 |  44 +++---
 flang/test/Lower/OpenMP/shared-loop.f90       |  66 ++++-----
 ...oop-reduction-allocatable-array-minmax.f90 |  20 ++-
 flang/test/Lower/OpenMP/wsloop-variable.f90   |  20 ++-
 flang/test/Lower/do_loop.f90                  | 140 ++++++++----------
 flang/test/Lower/do_loop_unstructured.f90     |  22 ++-
 flang/test/Lower/infinite_loop.f90            |  16 +-
 flang/test/Lower/loops2.f90                   |  44 +++---
 flang/test/Lower/mixed_loops.f90              |  22 ++-
 12 files changed, 240 insertions(+), 290 deletions(-)

diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 34d1346d6b285..d5b9cef8d4ca4 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -3205,26 +3205,26 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
         // End fir.do_loop. The loop carries no secondary-induction iter_arg, so
         // materialize the Fortran post-loop value lb + tripCount*step after the
-        // loop for later uses of the DO variable.
+        // loop for later uses of the DO variable. Compute it in the loop's
+        // index type (matching how the loop counts iterations) so the trip
+        // arithmetic does not overflow the DO variable's type for empty
+        // range-extreme loops.
         auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp);
         builder->setInsertionPointAfter(doLoopOp);
-        mlir::Type type = info.getLoopVariableType();
-        mlir::Value lb =
-            builder->createConvert(loc, type, doLoopOp.getLowerBound());
-        mlir::Value ub =
-            builder->createConvert(loc, type, doLoopOp.getUpperBound());
-        mlir::Value st = builder->createConvert(loc, type, doLoopOp.getStep());
-        mlir::Value zero = builder->createIntegerConstant(loc, type, 0);
-        mlir::Value trip =
-            mlir::arith::SubIOp::create(*builder, loc, ub, lb, iofAttr);
-        trip = mlir::arith::AddIOp::create(*builder, loc, trip, st, iofAttr);
+        mlir::Value lb = doLoopOp.getLowerBound();
+        mlir::Value ub = doLoopOp.getUpperBound();
+        mlir::Value st = doLoopOp.getStep();
+        mlir::Type idxTy = lb.getType();
+        mlir::Value zero = builder->createIntegerConstant(loc, idxTy, 0);
+        mlir::Value trip = mlir::arith::SubIOp::create(*builder, loc, ub, lb);
+        trip = mlir::arith::AddIOp::create(*builder, loc, trip, st);
         trip = mlir::arith::DivSIOp::create(*builder, loc, trip, st);
         mlir::Value empty = mlir::arith::CmpIOp::create(
             *builder, loc, mlir::arith::CmpIPredicate::slt, trip, zero);
         trip = mlir::arith::SelectOp::create(*builder, loc, empty, zero, trip);
-        mlir::Value last =
-            mlir::arith::MulIOp::create(*builder, loc, trip, st, iofAttr);
-        last = mlir::arith::AddIOp::create(*builder, loc, lb, last, iofAttr);
+        mlir::Value last = mlir::arith::MulIOp::create(*builder, loc, trip, st);
+        last = mlir::arith::AddIOp::create(*builder, loc, lb, last);
+        last = builder->createConvert(loc, info.getLoopVariableType(), last);
         fir::StoreOp::create(*builder, loc, last, info.loopVariable);
         continue;
       }
diff --git a/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90 b/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
index 4b73ce2fd1016..802a5fe18e6dd 100644
--- a/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
+++ b/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
@@ -22,21 +22,19 @@ subroutine sb1
 !CHECK:    %[[I_DECL:.*]]:2 = hlfir.declare %[[I_ADDR]] {uniq_name = "_QFsb1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 !CHECK:    omp.parallel private({{.*}} %[[I_DECL]]#0 -> %[[I_PVT_ADDR:.*]] : {{.*}}) {
 !CHECK:      %[[I_PVT_DECL:.*]]:2 = hlfir.declare %[[I_PVT_ADDR]] {uniq_name = "_QFsb1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
-!CHECK:      fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:      fir.do_loop %{{.*}} = %[[I_LB:.*]] to %[[I_UB:.*]] step %[[I_ST:.*]] {
 !CHECK:        %[[I_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
 !CHECK:        fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      }
-!CHECK:      %[[I_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:      %[[I_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:      %[[I_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:      %[[I_C0:.*]] = arith.constant 0 : i32
-!CHECK:      %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] overflow<nsw> : i32
-!CHECK:      %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] overflow<nsw> : i32
-!CHECK:      %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : i32
-!CHECK:      %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : i32
-!CHECK:      %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : i32
-!CHECK:      %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] overflow<nsw> : i32
-!CHECK:      %[[I_FINAL_VAL:.*]] = arith.addi %[[I_LB]], %[[I_M]] overflow<nsw> : i32
+!CHECK:      %[[I_C0:.*]] = arith.constant 0 : index
+!CHECK:      %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] : index
+!CHECK:      %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] : index
+!CHECK:      %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : index
+!CHECK:      %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : index
+!CHECK:      %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : index
+!CHECK:      %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] : index
+!CHECK:      %[[I_IDX:.*]] = arith.addi %[[I_LB]], %[[I_M]] : index
+!CHECK:      %[[I_FINAL_VAL:.*]] = fir.convert %[[I_IDX]] : (index) -> i32
 !CHECK:      fir.store %[[I_FINAL_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      omp.terminator
 !CHECK:    }
@@ -70,55 +68,49 @@ subroutine sb2
 
 !CHECK:      %[[I_PVT_DECL:.*]]:2 = hlfir.declare %[[I_PVT_ADDR]] {uniq_name = "_QFsb2Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 
-!CHECK:      fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:      fir.do_loop %{{.*}} = %[[J_LB:.*]] to %[[J_UB:.*]] step %[[J_ST:.*]] {
 !CHECK:        %[[J_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
 !CHECK:        fir.store %[[J_VAL]] to %[[J_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        fir.if %{{.*}} {
-!CHECK:          fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:          fir.do_loop %{{.*}} = %[[I_LB:.*]] to %[[I_UB:.*]] step %[[I_ST:.*]] {
 !CHECK:            %[[I_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
 !CHECK:            fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:          }
-!CHECK:          %[[I_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:          %[[I_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:          %[[I_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:          %[[I_C0:.*]] = arith.constant 0 : i32
-!CHECK:          %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] overflow<nsw> : i32
-!CHECK:          %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] overflow<nsw> : i32
-!CHECK:          %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : i32
-!CHECK:          %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : i32
-!CHECK:          %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : i32
-!CHECK:          %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] overflow<nsw> : i32
-!CHECK:          %[[FINAL_I_VAL:.*]] = arith.addi %[[I_LB]], %[[I_M]] overflow<nsw> : i32
+!CHECK:          %[[I_C0:.*]] = arith.constant 0 : index
+!CHECK:          %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] : index
+!CHECK:          %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] : index
+!CHECK:          %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : index
+!CHECK:          %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : index
+!CHECK:          %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : index
+!CHECK:          %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] : index
+!CHECK:          %[[I_IDX:.*]] = arith.addi %[[I_LB]], %[[I_M]] : index
+!CHECK:          %[[FINAL_I_VAL:.*]] = fir.convert %[[I_IDX]] : (index) -> i32
 !CHECK:          fir.store %[[FINAL_I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        }
-!CHECK:        fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+!CHECK:        fir.do_loop %{{.*}} = %[[I2_LB:.*]] to %[[I2_UB:.*]] step %[[I2_ST:.*]] {
 !CHECK:          %[[I_VAL2:.*]] = fir.convert %{{.*}} : (index) -> i32
 !CHECK:          fir.store %[[I_VAL2]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        }
-!CHECK:        %[[I2_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:        %[[I2_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:        %[[I2_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:        %[[I2_C0:.*]] = arith.constant 0 : i32
-!CHECK:        %[[I2_D:.*]] = arith.subi %[[I2_UB]], %[[I2_LB]] overflow<nsw> : i32
-!CHECK:        %[[I2_A:.*]] = arith.addi %[[I2_D]], %[[I2_ST]] overflow<nsw> : i32
-!CHECK:        %[[I2_TR:.*]] = arith.divsi %[[I2_A]], %[[I2_ST]] : i32
-!CHECK:        %[[I2_CMP:.*]] = arith.cmpi slt, %[[I2_TR]], %[[I2_C0]] : i32
-!CHECK:        %[[I2_SEL:.*]] = arith.select %[[I2_CMP]], %[[I2_C0]], %[[I2_TR]] : i32
-!CHECK:        %[[I2_M:.*]] = arith.muli %[[I2_SEL]], %[[I2_ST]] overflow<nsw> : i32
-!CHECK:        %[[FINAL_I_VAL2:.*]] = arith.addi %[[I2_LB]], %[[I2_M]] overflow<nsw> : i32
+!CHECK:        %[[I2_C0:.*]] = arith.constant 0 : index
+!CHECK:        %[[I2_D:.*]] = arith.subi %[[I2_UB]], %[[I2_LB]] : index
+!CHECK:        %[[I2_A:.*]] = arith.addi %[[I2_D]], %[[I2_ST]] : index
+!CHECK:        %[[I2_TR:.*]] = arith.divsi %[[I2_A]], %[[I2_ST]] : index
+!CHECK:        %[[I2_CMP:.*]] = arith.cmpi slt, %[[I2_TR]], %[[I2_C0]] : index
+!CHECK:        %[[I2_SEL:.*]] = arith.select %[[I2_CMP]], %[[I2_C0]], %[[I2_TR]] : index
+!CHECK:        %[[I2_M:.*]] = arith.muli %[[I2_SEL]], %[[I2_ST]] : index
+!CHECK:        %[[I2_IDX:.*]] = arith.addi %[[I2_LB]], %[[I2_M]] : index
+!CHECK:        %[[FINAL_I_VAL2:.*]] = fir.convert %[[I2_IDX]] : (index) -> i32
 !CHECK:        fir.store %[[FINAL_I_VAL2]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      }
-!CHECK:      %[[J_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:      %[[J_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:      %[[J_ST:.*]] = fir.convert %{{.*}} : (index) -> i32
-!CHECK:      %[[J_C0:.*]] = arith.constant 0 : i32
-!CHECK:      %[[J_D:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
-!CHECK:      %[[J_A:.*]] = arith.addi %[[J_D]], %[[J_ST]] overflow<nsw> : i32
-!CHECK:      %[[J_TR:.*]] = arith.divsi %[[J_A]], %[[J_ST]] : i32
-!CHECK:      %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TR]], %[[J_C0]] : i32
-!CHECK:      %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TR]] : i32
-!CHECK:      %[[J_M:.*]] = arith.muli %[[J_SEL]], %[[J_ST]] overflow<nsw> : i32
-!CHECK:      %[[FINAL_J_VAL:.*]] = arith.addi %[[J_LB]], %[[J_M]] overflow<nsw> : i32
+!CHECK:      %[[J_C0:.*]] = arith.constant 0 : index
+!CHECK:      %[[J_D:.*]] = arith.subi %[[J_UB]], %[[J_LB]] : index
+!CHECK:      %[[J_A:.*]] = arith.addi %[[J_D]], %[[J_ST]] : index
+!CHECK:      %[[J_TR:.*]] = arith.divsi %[[J_A]], %[[J_ST]] : index
+!CHECK:      %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TR]], %[[J_C0]] : index
+!CHECK:      %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TR]] : index
+!CHECK:      %[[J_M:.*]] = arith.muli %[[J_SEL]], %[[J_ST]] : index
+!CHECK:      %[[J_IDX:.*]] = arith.addi %[[J_LB]], %[[J_M]] : index
+!CHECK:      %[[FINAL_J_VAL:.*]] = fir.convert %[[J_IDX]] : (index) -> i32
 !CHECK:      fir.store %[[FINAL_J_VAL]] to %[[J_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      omp.terminator
 !CHECK:    }
diff --git a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
index a061d897456bd..f1f2c2d2ba7e3 100644
--- a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
+++ b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
@@ -66,17 +66,15 @@
 ! CHECK:                 %[[VAL_16:.*]] = arith.addi %[[LOAD]], %[[VAL_15]] : i32
 ! CHECK:                 hlfir.assign %[[VAL_16]] to %[[PRIV_X_DECL]]#0 : i32, !fir.ref<i32>
 ! CHECK:               }
-! CHECK:               %[[LB:.*]] = fir.convert %[[VAL_8]] : (index) -> i32
-! CHECK:               %[[UB:.*]] = fir.convert %[[VAL_10]] : (index) -> i32
-! CHECK:               %[[STEP:.*]] = fir.convert %[[VAL_11]] : (index) -> i32
-! CHECK:               %[[C0:.*]] = arith.constant 0 : i32
-! CHECK:               %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-! CHECK:               %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-! CHECK:               %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-! CHECK:               %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CHECK:               %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CHECK:               %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-! CHECK:               %[[VAL_12:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:               %[[C0:.*]] = arith.constant 0 : index
+! CHECK:               %[[DIFF:.*]] = arith.subi %[[VAL_10]], %[[VAL_8]] : index
+! CHECK:               %[[ADD:.*]] = arith.addi %[[DIFF]], %[[VAL_11]] : index
+! CHECK:               %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[VAL_11]] : index
+! CHECK:               %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+! CHECK:               %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+! CHECK:               %[[MUL:.*]] = arith.muli %[[SEL]], %[[VAL_11]] : index
+! CHECK:               %[[IDX:.*]] = arith.addi %[[VAL_8]], %[[MUL]] : index
+! CHECK:               %[[VAL_12:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:               fir.store %[[VAL_12]] to %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:               omp.yield
 ! CHECK:             }
diff --git a/flang/test/Lower/OpenMP/sections-predetermined-private.f90 b/flang/test/Lower/OpenMP/sections-predetermined-private.f90
index aaf7c125e1b95..66de7359c42bf 100644
--- a/flang/test/Lower/OpenMP/sections-predetermined-private.f90
+++ b/flang/test/Lower/OpenMP/sections-predetermined-private.f90
@@ -15,40 +15,36 @@
 ! CHECK:             %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 ! CHECK:             omp.sections {
 ! CHECK:               omp.section {
-! CHECK:                 fir.do_loop %[[VAL_12:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:                 fir.do_loop %[[VAL_12:.*]] = %[[LB1:.*]] to %[[UB1:.*]] step %[[ST1:.*]] {
 ! CHECK:                   %[[VAL_IV:.*]] = fir.convert %[[VAL_12]] : (index) -> i32
 ! CHECK:                   fir.store %[[VAL_IV]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 }
-! CHECK:                 %[[LB1:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:                 %[[UB1:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:                 %[[ST1:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:                 %[[C01:.*]] = arith.constant 0 : i32
-! CHECK:                 %[[D1:.*]] = arith.subi %[[UB1]], %[[LB1]] overflow<nsw> : i32
-! CHECK:                 %[[A1:.*]] = arith.addi %[[D1]], %[[ST1]] overflow<nsw> : i32
-! CHECK:                 %[[TR1:.*]] = arith.divsi %[[A1]], %[[ST1]] : i32
-! CHECK:                 %[[CMP1:.*]] = arith.cmpi slt, %[[TR1]], %[[C01]] : i32
-! CHECK:                 %[[SEL1:.*]] = arith.select %[[CMP1]], %[[C01]], %[[TR1]] : i32
-! CHECK:                 %[[M1:.*]] = arith.muli %[[SEL1]], %[[ST1]] overflow<nsw> : i32
-! CHECK:                 %[[LAST1:.*]] = arith.addi %[[LB1]], %[[M1]] overflow<nsw> : i32
+! CHECK:                 %[[C01:.*]] = arith.constant 0 : index
+! CHECK:                 %[[D1:.*]] = arith.subi %[[UB1]], %[[LB1]] : index
+! CHECK:                 %[[A1:.*]] = arith.addi %[[D1]], %[[ST1]] : index
+! CHECK:                 %[[TR1:.*]] = arith.divsi %[[A1]], %[[ST1]] : index
+! CHECK:                 %[[CMP1:.*]] = arith.cmpi slt, %[[TR1]], %[[C01]] : index
+! CHECK:                 %[[SEL1:.*]] = arith.select %[[CMP1]], %[[C01]], %[[TR1]] : index
+! CHECK:                 %[[M1:.*]] = arith.muli %[[SEL1]], %[[ST1]] : index
+! CHECK:                 %[[LAST1IDX:.*]] = arith.addi %[[LB1]], %[[M1]] : index
+! CHECK:                 %[[LAST1:.*]] = fir.convert %[[LAST1IDX]] : (index) -> i32
 ! CHECK:                 fir.store %[[LAST1]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 omp.terminator
 ! CHECK:               }
 ! CHECK:               omp.section {
-! CHECK:                 fir.do_loop %[[VAL_26:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:                 fir.do_loop %[[VAL_26:.*]] = %[[LB2:.*]] to %[[UB2:.*]] step %[[ST2:.*]] {
 ! CHECK:                   %[[VAL_IV2:.*]] = fir.convert %[[VAL_26]] : (index) -> i32
 ! CHECK:                   fir.store %[[VAL_IV2]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 }
-! CHECK:                 %[[LB2:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:                 %[[UB2:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:                 %[[ST2:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:                 %[[C02:.*]] = arith.constant 0 : i32
-! CHECK:                 %[[D2:.*]] = arith.subi %[[UB2]], %[[LB2]] overflow<nsw> : i32
-! CHECK:                 %[[A2:.*]] = arith.addi %[[D2]], %[[ST2]] overflow<nsw> : i32
-! CHECK:                 %[[TR2:.*]] = arith.divsi %[[A2]], %[[ST2]] : i32
-! CHECK:                 %[[CMP2:.*]] = arith.cmpi slt, %[[TR2]], %[[C02]] : i32
-! CHECK:                 %[[SEL2:.*]] = arith.select %[[CMP2]], %[[C02]], %[[TR2]] : i32
-! CHECK:                 %[[M2:.*]] = arith.muli %[[SEL2]], %[[ST2]] overflow<nsw> : i32
-! CHECK:                 %[[LAST2:.*]] = arith.addi %[[LB2]], %[[M2]] overflow<nsw> : i32
+! CHECK:                 %[[C02:.*]] = arith.constant 0 : index
+! CHECK:                 %[[D2:.*]] = arith.subi %[[UB2]], %[[LB2]] : index
+! CHECK:                 %[[A2:.*]] = arith.addi %[[D2]], %[[ST2]] : index
+! CHECK:                 %[[TR2:.*]] = arith.divsi %[[A2]], %[[ST2]] : index
+! CHECK:                 %[[CMP2:.*]] = arith.cmpi slt, %[[TR2]], %[[C02]] : index
+! CHECK:                 %[[SEL2:.*]] = arith.select %[[CMP2]], %[[C02]], %[[TR2]] : index
+! CHECK:                 %[[M2:.*]] = arith.muli %[[SEL2]], %[[ST2]] : index
+! CHECK:                 %[[LAST2IDX:.*]] = arith.addi %[[LB2]], %[[M2]] : index
+! CHECK:                 %[[LAST2:.*]] = fir.convert %[[LAST2IDX]] : (index) -> i32
 ! CHECK:                 fir.store %[[LAST2]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 omp.terminator
 ! CHECK:               }
diff --git a/flang/test/Lower/OpenMP/shared-loop.f90 b/flang/test/Lower/OpenMP/shared-loop.f90
index 42aefc932e54f..cf6f24cc499ef 100644
--- a/flang/test/Lower/OpenMP/shared-loop.f90
+++ b/flang/test/Lower/OpenMP/shared-loop.f90
@@ -9,22 +9,20 @@
 ! CHECK:    omp.parallel {
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
 ! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
 ! CHECK:            fir.store %[[IV]] to %[[DECL_I]]#0
 ! CHECK:            hlfir.assign
 ! CHECK:          }
-! CHECK:          %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[C0:.*]] = arith.constant 0 : i32
-! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : i32
-! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-! CHECK:          %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:          %[[C0:.*]] = arith.constant 0 : index
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : index
+! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
+! CHECK:          %[[IDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK:          %[[LAST:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:          fir.store %[[LAST]] to %[[DECL_I]]#0
 ! CHECK:          omp.terminator
 ! CHECK:        }
@@ -56,23 +54,21 @@ subroutine omploop
 ! CHECK:      %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
 ! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
 ! CHECK-NOT:            fir.store %{{.*}} to %[[DECL_I]]#1
 ! CHECK:            fir.store %[[IV]] to %[[DECL_PRIV_I]]#0
 ! CHECK:            hlfir.assign
 ! CHECK:          }
-! CHECK:          %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[C0:.*]] = arith.constant 0 : i32
-! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : i32
-! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-! CHECK:          %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:          %[[C0:.*]] = arith.constant 0 : index
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : index
+! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
+! CHECK:          %[[IDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK:          %[[LAST:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:          fir.store %[[LAST]] to %[[DECL_PRIV_I]]#0
 ! CHECK:          omp.terminator
 ! CHECK:        }
@@ -105,23 +101,21 @@ subroutine omploop2
 ! CHECK:      %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
 ! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
 ! CHECK-NOT:            fir.store %{{.*}} to %[[DECL_I]]#1
 ! CHECK:            fir.store %[[IV]] to %[[DECL_PRIV_I]]#0
 ! CHECK:            hlfir.assign
 ! CHECK:          }
-! CHECK:          %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:          %[[C0:.*]] = arith.constant 0 : i32
-! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : i32
-! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-! CHECK:          %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:          %[[C0:.*]] = arith.constant 0 : index
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : index
+! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
+! CHECK:          %[[IDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK:          %[[LAST:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:          fir.store %[[LAST]] to %[[DECL_PRIV_I]]#0
 ! CHECK:          omp.terminator
 ! CHECK:        }
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
index 1a606f64a7d34..da0892edf6588 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
@@ -211,17 +211,15 @@ program reduce15
 ! CHECK:             %[[VAL_49:.*]] = hlfir.designate %[[VAL_46]] (%[[VAL_48]])  : (!fir.box<!fir.heap<!fir.array<?xi32>>>, i64) -> !fir.ref<i32>
 ! CHECK:             hlfir.assign %[[VAL_45]] to %[[VAL_49]] : i32, !fir.ref<i32>
 ! CHECK:           }
-! CHECK:           %[[VAL_LB:.*]] = fir.convert %[[VAL_37]] : (index) -> i32
-! CHECK:           %[[VAL_UB:.*]] = fir.convert %[[VAL_39]] : (index) -> i32
-! CHECK:           %[[VAL_ST:.*]] = fir.convert %[[VAL_40]] : (index) -> i32
-! CHECK:           %[[VAL_C0:.*]] = arith.constant 0 : i32
-! CHECK:           %[[VAL_DIFF:.*]] = arith.subi %[[VAL_UB]], %[[VAL_LB]] overflow<nsw> : i32
-! CHECK:           %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_ST]] overflow<nsw> : i32
-! CHECK:           %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_ST]] : i32
-! CHECK:           %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : i32
-! CHECK:           %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : i32
-! CHECK:           %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_ST]] overflow<nsw> : i32
-! CHECK:           %[[VAL_54:.*]] = arith.addi %[[VAL_LB]], %[[VAL_MUL]] overflow<nsw> : i32
+! CHECK:           %[[VAL_C0:.*]] = arith.constant 0 : index
+! CHECK:           %[[VAL_DIFF:.*]] = arith.subi %[[VAL_39]], %[[VAL_37]] : index
+! CHECK:           %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_40]] : index
+! CHECK:           %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_40]] : index
+! CHECK:           %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : index
+! CHECK:           %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : index
+! CHECK:           %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_40]] : index
+! CHECK:           %[[VAL_IDX:.*]] = arith.addi %[[VAL_37]], %[[VAL_MUL]] : index
+! CHECK:           %[[VAL_54:.*]] = fir.convert %[[VAL_IDX]] : (index) -> i32
 ! CHECK:           fir.store %[[VAL_54]] to %[[VAL_3]]#0 : !fir.ref<i32>
 ! CHECK:           omp.parallel {
 ! CHECK:             %[[VAL_57:.*]] = arith.constant 1 : i32
diff --git a/flang/test/Lower/OpenMP/wsloop-variable.f90 b/flang/test/Lower/OpenMP/wsloop-variable.f90
index 02e47f7aa212e..155e4f7d7b700 100644
--- a/flang/test/Lower/OpenMP/wsloop-variable.f90
+++ b/flang/test/Lower/OpenMP/wsloop-variable.f90
@@ -148,17 +148,15 @@ subroutine wsloop_variable_sub
 !CHECK:                 %[[VAL_43:.*]] = fir.convert %[[VAL_42]] : (i64) -> f32
 !CHECK:                 hlfir.assign %[[VAL_43]] to %[[VAL_21]]#0 : f32, !fir.ref<f32>
 !CHECK:               }
-!CHECK:               %[[VAL_LB:.*]] = fir.convert %[[VAL_30]] : (index) -> i64
-!CHECK:               %[[VAL_UB:.*]] = fir.convert %[[VAL_32]] : (index) -> i64
-!CHECK:               %[[VAL_ST:.*]] = fir.convert %[[VAL_34]] : (index) -> i64
-!CHECK:               %[[VAL_C0:.*]] = arith.constant 0 : i64
-!CHECK:               %[[VAL_DIFF:.*]] = arith.subi %[[VAL_UB]], %[[VAL_LB]] overflow<nsw> : i64
-!CHECK:               %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_ST]] overflow<nsw> : i64
-!CHECK:               %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_ST]] : i64
-!CHECK:               %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : i64
-!CHECK:               %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : i64
-!CHECK:               %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_ST]] overflow<nsw> : i64
-!CHECK:               %[[VAL_48:.*]] = arith.addi %[[VAL_LB]], %[[VAL_MUL]] overflow<nsw> : i64
+!CHECK:               %[[VAL_C0:.*]] = arith.constant 0 : index
+!CHECK:               %[[VAL_DIFF:.*]] = arith.subi %[[VAL_32]], %[[VAL_30]] : index
+!CHECK:               %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_34]] : index
+!CHECK:               %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_34]] : index
+!CHECK:               %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : index
+!CHECK:               %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : index
+!CHECK:               %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_34]] : index
+!CHECK:               %[[VAL_LAST:.*]] = arith.addi %[[VAL_30]], %[[VAL_MUL]] : index
+!CHECK:               %[[VAL_48:.*]] = fir.convert %[[VAL_LAST]] : (index) -> i64
 !CHECK:               fir.store %[[VAL_48]] to %[[VAL_17]]#0 : !fir.ref<i64>
 !CHECK:               omp.yield
 !CHECK:             }
diff --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90
index 91be10a7d076d..269123a8f3c4b 100644
--- a/flang/test/Lower/do_loop.f90
+++ b/flang/test/Lower/do_loop.f90
@@ -26,17 +26,15 @@ subroutine simple_loop
   ! CHECK:   fir.store %[[IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
-  ! CHECK: %[[LB:.*]] = fir.convert %[[C1_CVT]] : (index) -> i32
-  ! CHECK: %[[UB:.*]] = fir.convert %[[C5_CVT]] : (index) -> i32
-  ! CHECK: %[[STEP:.*]] = fir.convert %[[C1_STEP]] : (index) -> i32
-  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
-  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : index
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C5_CVT]], %[[C1_CVT]] : index
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[C1_STEP]] : index
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[C1_STEP]] : index
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[C1_STEP]] : index
+  ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[C1_CVT]], %[[MUL]] : index
+  ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
   ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: %[[I:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: %{{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[I]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
@@ -87,31 +85,27 @@ subroutine nested_loop
       asum = asum + arr(i,j)
     ! CHECK: }
     end do
-    ! CHECK: %[[J_LB:.*]] = fir.convert %[[S_J_CVT]] : (index) -> i32
-    ! CHECK: %[[J_UB:.*]] = fir.convert %[[E_J_CVT]] : (index) -> i32
-    ! CHECK: %[[J_STEP:.*]] = fir.convert %[[ST_J]] : (index) -> i32
-    ! CHECK: %[[J_C0:.*]] = arith.constant 0 : i32
-    ! CHECK: %[[J_DIFF:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
-    ! CHECK: %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[J_STEP]] overflow<nsw> : i32
-    ! CHECK: %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[J_STEP]] : i32
-    ! CHECK: %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : i32
-    ! CHECK: %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : i32
-    ! CHECK: %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[J_STEP]] overflow<nsw> : i32
-    ! CHECK: %[[J_LAST:.*]] = arith.addi %[[J_LB]], %[[J_MUL]] overflow<nsw> : i32
+    ! CHECK: %[[J_C0:.*]] = arith.constant 0 : index
+    ! CHECK: %[[J_DIFF:.*]] = arith.subi %[[E_J_CVT]], %[[S_J_CVT]] : index
+    ! CHECK: %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[ST_J]] : index
+    ! CHECK: %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[ST_J]] : index
+    ! CHECK: %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : index
+    ! CHECK: %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : index
+    ! CHECK: %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[ST_J]] : index
+    ! CHECK: %[[J_LASTIDX:.*]] = arith.addi %[[S_J_CVT]], %[[J_MUL]] : index
+    ! CHECK: %[[J_LAST:.*]] = fir.convert %[[J_LASTIDX]] : (index) -> i32
     ! CHECK: fir.store %[[J_LAST]] to %[[J_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
-  ! CHECK: %[[I_LB:.*]] = fir.convert %[[S_I_CVT]] : (index) -> i32
-  ! CHECK: %[[I_UB:.*]] = fir.convert %[[E_I_CVT]] : (index) -> i32
-  ! CHECK: %[[I_STEP:.*]] = fir.convert %[[ST_I]] : (index) -> i32
-  ! CHECK: %[[I_C0:.*]] = arith.constant 0 : i32
-  ! CHECK: %[[I_DIFF:.*]] = arith.subi %[[I_UB]], %[[I_LB]] overflow<nsw> : i32
-  ! CHECK: %[[I_ADD:.*]] = arith.addi %[[I_DIFF]], %[[I_STEP]] overflow<nsw> : i32
-  ! CHECK: %[[I_TRIP:.*]] = arith.divsi %[[I_ADD]], %[[I_STEP]] : i32
-  ! CHECK: %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TRIP]], %[[I_C0]] : i32
-  ! CHECK: %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TRIP]] : i32
-  ! CHECK: %[[I_MUL:.*]] = arith.muli %[[I_SEL]], %[[I_STEP]] overflow<nsw> : i32
-  ! CHECK: %[[I_LAST:.*]] = arith.addi %[[I_LB]], %[[I_MUL]] overflow<nsw> : i32
+  ! CHECK: %[[I_C0:.*]] = arith.constant 0 : index
+  ! CHECK: %[[I_DIFF:.*]] = arith.subi %[[E_I_CVT]], %[[S_I_CVT]] : index
+  ! CHECK: %[[I_ADD:.*]] = arith.addi %[[I_DIFF]], %[[ST_I]] : index
+  ! CHECK: %[[I_TRIP:.*]] = arith.divsi %[[I_ADD]], %[[ST_I]] : index
+  ! CHECK: %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TRIP]], %[[I_C0]] : index
+  ! CHECK: %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TRIP]] : index
+  ! CHECK: %[[I_MUL:.*]] = arith.muli %[[I_SEL]], %[[ST_I]] : index
+  ! CHECK: %[[I_LASTIDX:.*]] = arith.addi %[[S_I_CVT]], %[[I_MUL]] : index
+  ! CHECK: %[[I_LAST:.*]] = fir.convert %[[I_LASTIDX]] : (index) -> i32
   ! CHECK: fir.store %[[I_LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
 end subroutine
 
@@ -134,17 +128,15 @@ subroutine down_counting_loop()
   ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
-  ! CHECK: %[[LB:.*]] = fir.convert %[[C5_CVT]] : (index) -> i32
-  ! CHECK: %[[UB:.*]] = fir.convert %[[C1_CVT]] : (index) -> i32
-  ! CHECK: %[[STEP:.*]] = fir.convert %[[CMINUS1_STEP_CVT]] : (index) -> i32
-  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
-  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : index
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[C1_CVT]], %[[C5_CVT]] : index
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[CMINUS1_STEP_CVT]] : index
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[CMINUS1_STEP_CVT]] : index
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[CMINUS1_STEP_CVT]] : index
+  ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[C5_CVT]], %[[MUL]] : index
+  ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
   ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
 end subroutine
 
@@ -170,17 +162,15 @@ subroutine loop_with_variable_step(s,e,st)
   ! CHECK:  fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
-  ! CHECK: %[[LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32
-  ! CHECK: %[[UB:.*]] = fir.convert %[[E_CVT]] : (index) -> i32
-  ! CHECK: %[[STEP:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32
-  ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
-  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : index
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[E_CVT]], %[[S_CVT]] : index
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[ST_CVT]] : index
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[ST_CVT]] : index
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[ST_CVT]] : index
+  ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[S_CVT]], %[[MUL]] : index
+  ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
   ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
 end subroutine
 
@@ -229,17 +219,15 @@ subroutine loop_with_pointer_variables(s,e,st)
 ! CHECK:    fir.store %[[I_IV]] to %[[I_PTR]] : !fir.ptr<i32>
 ! CHECK:  }
   end do
-! CHECK:  %[[LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i32
-! CHECK:  %[[UB:.*]] = fir.convert %[[E_CVT]] : (index) -> i32
-! CHECK:  %[[STEP:.*]] = fir.convert %[[ST_CVT]] : (index) -> i32
-! CHECK:  %[[C0:.*]] = arith.constant 0 : i32
-! CHECK:  %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-! CHECK:  %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-! CHECK:  %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-! CHECK:  %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CHECK:  %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CHECK:  %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-! CHECK:  %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK:  %[[C0:.*]] = arith.constant 0 : index
+! CHECK:  %[[DIFF:.*]] = arith.subi %[[E_CVT]], %[[S_CVT]] : index
+! CHECK:  %[[ADD:.*]] = arith.addi %[[DIFF]], %[[ST_CVT]] : index
+! CHECK:  %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[ST_CVT]] : index
+! CHECK:  %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+! CHECK:  %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+! CHECK:  %[[MUL:.*]] = arith.muli %[[SEL]], %[[ST_CVT]] : index
+! CHECK:  %[[LASTIDX:.*]] = arith.addi %[[S_CVT]], %[[MUL]] : index
+! CHECK:  %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
 ! CHECK:  fir.store %[[LAST]] to %[[I_PTR]] : !fir.ptr<i32>
 end subroutine
 
@@ -267,17 +255,15 @@ subroutine loop_with_non_default_integer(s,e,st)
     ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i64>
   ! CHECK: }
   end do
-  ! CHECK: %[[LB:.*]] = fir.convert %[[S_CVT]] : (index) -> i64
-  ! CHECK: %[[UB:.*]] = fir.convert %[[E_CVT]] : (index) -> i64
-  ! CHECK: %[[STEP:.*]] = fir.convert %[[ST_CVT]] : (index) -> i64
-  ! CHECK: %[[C0:.*]] = arith.constant 0 : i64
-  ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i64
-  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i64
-  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i64
-  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i64
-  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i64
-  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i64
-  ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i64
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : index
+  ! CHECK: %[[DIFF:.*]] = arith.subi %[[E_CVT]], %[[S_CVT]] : index
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[ST_CVT]] : index
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[ST_CVT]] : index
+  ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+  ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[ST_CVT]] : index
+  ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[S_CVT]], %[[MUL]] : index
+  ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i64
   ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i64>
 end subroutine
 
diff --git a/flang/test/Lower/do_loop_unstructured.f90 b/flang/test/Lower/do_loop_unstructured.f90
index 5448647dbf27f..9a7b76eb090a9 100644
--- a/flang/test/Lower/do_loop_unstructured.f90
+++ b/flang/test/Lower/do_loop_unstructured.f90
@@ -170,21 +170,19 @@ subroutine nested_structured_in_unstructured()
 ! CHECK:   cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
 ! CHECK: ^[[BODY]]:
 ! CHECK:   fir.do_loop %[[J_INDEX:[^ ]*]] =
-! CHECK-SAME: %{{.*}} to %{{.*}} step %[[ST:[^ ]*]] {
+! CHECK-SAME: %[[J_LBIDX:[^ ]*]] to %[[J_UBIDX:[^ ]*]] step %[[ST:[^ ]*]] {
 ! CHECK:     %[[J_IV:.*]] = fir.convert %[[J_INDEX]] : (index) -> i32
 ! CHECK:     fir.store %[[J_IV]] to %[[LOOP_VAR_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   }
-! CHECK:   %[[J_LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:   %[[J_UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:   %[[J_STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK:   %[[J_C0:.*]] = arith.constant 0 : i32
-! CHECK:   %[[J_DIFF:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
-! CHECK:   %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[J_STEP]] overflow<nsw> : i32
-! CHECK:   %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[J_STEP]] : i32
-! CHECK:   %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : i32
-! CHECK:   %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : i32
-! CHECK:   %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[J_STEP]] overflow<nsw> : i32
-! CHECK:   %[[J_LAST:.*]] = arith.addi %[[J_LB]], %[[J_MUL]] overflow<nsw> : i32
+! CHECK:   %[[J_C0:.*]] = arith.constant 0 : index
+! CHECK:   %[[J_DIFF:.*]] = arith.subi %[[J_UBIDX]], %[[J_LBIDX]] : index
+! CHECK:   %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[ST]] : index
+! CHECK:   %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[ST]] : index
+! CHECK:   %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : index
+! CHECK:   %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : index
+! CHECK:   %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[ST]] : index
+! CHECK:   %[[J_LASTIDX:.*]] = arith.addi %[[J_LBIDX]], %[[J_MUL]] : index
+! CHECK:   %[[J_LAST:.*]] = fir.convert %[[J_LASTIDX]] : (index) -> i32
 ! CHECK:   fir.store %[[J_LAST]] to %[[LOOP_VAR_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
 ! CHECK:   %[[C1_3:.*]] = arith.constant 1 : i32
diff --git a/flang/test/Lower/infinite_loop.f90 b/flang/test/Lower/infinite_loop.f90
index c5f2196ff01be..d58473ccbf049 100644
--- a/flang/test/Lower/infinite_loop.f90
+++ b/flang/test/Lower/infinite_loop.f90
@@ -101,16 +101,12 @@ subroutine structured_loop_in_infinite(i)
 ! CHECK:    %[[J_IV:.*]] = fir.convert %[[J]] : (index) -> i32
 ! CHECK:    fir.store %[[J_IV]] to %[[J_DECL]] : !fir.ref<i32>
 ! CHECK:  }
-! CHECK:  %[[J_LB:.*]] = fir.convert %[[C1_INDEX]] : (index) -> i32
-! CHECK:  %[[J_UB:.*]] = fir.convert %[[C10_INDEX]] : (index) -> i32
-! CHECK:  %[[J_STEP:.*]] = fir.convert %[[C1_1]] : (index) -> i32
-! CHECK:  %[[J_DIFF:.*]] = arith.subi %[[J_UB]], %[[J_LB]] overflow<nsw> : i32
-! CHECK:  %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[J_STEP]] overflow<nsw> : i32
-! CHECK:  %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[J_STEP]] : i32
-! CHECK:  %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %{{.*}} : i32
-! CHECK:  %[[J_SEL:.*]] = arith.select %[[J_CMP]], %{{.*}}, %[[J_TRIP]] : i32
-! CHECK:  %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[J_STEP]] overflow<nsw> : i32
-! CHECK:  %[[J_LAST:.*]] = arith.addi %[[J_LB]], %[[J_MUL]] overflow<nsw> : i32
+! CHECK:  %[[J_DIFF:.*]] = arith.subi %[[C10_INDEX]], %[[C1_INDEX]] : index
+! CHECK:  %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[C1_1]] : index
+! CHECK:  %[[J_CMP:.*]] = arith.cmpi slt, %[[J_ADD]], %{{.*}} : index
+! CHECK:  %[[J_SEL:.*]] = arith.select %[[J_CMP]], %{{.*}}, %[[J_ADD]] : index
+! CHECK:  %[[J_LASTIDX:.*]] = arith.addi %[[C1_INDEX]], %[[J_SEL]] : index
+! CHECK:  %[[J_LAST:.*]] = fir.convert %[[J_LASTIDX]] : (index) -> i32
 ! CHECK:  fir.store %[[J_LAST]] to %[[J_DECL]] : !fir.ref<i32>
 ! CHECK:  cf.br ^[[BODY1]]
 ! CHECK: ^[[RETURN]]:
diff --git a/flang/test/Lower/loops2.f90 b/flang/test/Lower/loops2.f90
index c925c210d737d..78517aa013d6c 100644
--- a/flang/test/Lower/loops2.f90
+++ b/flang/test/Lower/loops2.f90
@@ -15,20 +15,18 @@ subroutine test_pointer()
 ! CHECK: %[[PTR:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMtest_loop_varEi_pointer"}
 ! CHECK: %[[BOX:.*]] = fir.load %[[PTR]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
 ! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
-! CHECK: fir.do_loop
+! CHECK: fir.do_loop %{{.*}} = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
 ! CHECK:   fir.store %{{.*}} to %[[ADDR]] : !fir.ptr<i32>
 ! CHECK: }
-! CHECK: %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK: %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK: %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK: %[[C0:.*]] = arith.constant 0 : i32
-! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : index
+! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
+! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
+! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : index
+! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
+! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
 ! CHECK: fir.store %[[LAST]] to %[[ADDR]] : !fir.ptr<i32>
   end subroutine
 
@@ -39,20 +37,18 @@ subroutine test_allocatable()
 ! CHECK: %[[ALLOC:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMtest_loop_varEi_allocatable"}
 ! CHECK: %[[BOX:.*]] = fir.load %[[ALLOC]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
 ! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
-! CHECK: fir.do_loop
+! CHECK: fir.do_loop %{{.*}} = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
 ! CHECK:   fir.store %{{.*}} to %[[ADDR]] : !fir.heap<i32>
 ! CHECK: }
-! CHECK: %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK: %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK: %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
-! CHECK: %[[C0:.*]] = arith.constant 0 : i32
-! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : index
+! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
+! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
+! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : index
+! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
+! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
 ! CHECK: fir.store %[[LAST]] to %[[ADDR]] : !fir.heap<i32>
   end subroutine
 
diff --git a/flang/test/Lower/mixed_loops.f90 b/flang/test/Lower/mixed_loops.f90
index 4fa9f9bf6d289..f62a40c5d4b83 100644
--- a/flang/test/Lower/mixed_loops.f90
+++ b/flang/test/Lower/mixed_loops.f90
@@ -77,7 +77,7 @@ subroutine do_inside_while_loop
       ! 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 %[[LI:.*]] = %{{.*}} to %{{.*}} step %{{.*}} {
+      ! CHECK: fir.do_loop %[[LI:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
         ! CHECK: %[[IV:.*]] = fir.convert %[[LI]] : (index) -> i32
         ! CHECK: fir.store %[[IV]] to %[[I]]#0 : !fir.ref<i32>
         ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
@@ -87,17 +87,15 @@ subroutine do_inside_while_loop
       do i=8,13
         j=j*2
 
-      ! CHECK: %[[LB:.*]] = fir.convert %{{.*}} : (index) -> i32
-      ! CHECK: %[[UB:.*]] = fir.convert %{{.*}} : (index) -> i32
-      ! CHECK: %[[STEP:.*]] = fir.convert %{{.*}} : (index) -> i32
-      ! CHECK: %[[C0:.*]] = arith.constant 0 : i32
-      ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] overflow<nsw> : i32
-      ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] overflow<nsw> : i32
-      ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : i32
-      ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : i32
-      ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : i32
-      ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] overflow<nsw> : i32
-      ! CHECK: %[[LAST:.*]] = arith.addi %[[LB]], %[[MUL]] overflow<nsw> : i32
+      ! CHECK: %[[C0:.*]] = arith.constant 0 : index
+      ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
+      ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
+      ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : index
+      ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
+      ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
+      ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
+      ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+      ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
       ! CHECK: fir.store %[[LAST]] to %[[I]]#0 : !fir.ref<i32>
       end do
 

>From 3d888cbbb0d3b4523bdf8a818fca5faac7f8e45f Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Fri, 17 Jul 2026 16:17:36 -0700
Subject: [PATCH 11/12] [flang] Preserve DO variable type in fir.do_loop

Use the source integer type for plain DO induction so removing the secondary induction does not regress vectorization; keep trip-count arithmetic in index type.
---
 .../include/flang/Optimizer/Dialect/FIROps.td | 10 +-
 flang/lib/Lower/Bridge.cpp                    | 23 +++--
 flang/lib/Optimizer/Dialect/FIROps.cpp        | 51 ++++++----
 .../Optimizer/Transforms/AffinePromotion.cpp  |  2 +
 .../Transforms/ControlFlowConverter.cpp       | 15 ++-
 flang/lib/Optimizer/Transforms/FIRToSCF.cpp   | 54 +++++++---
 flang/test/Fir/FirToSCF/do-loop.fir           | 26 +++++
 flang/test/Fir/loop01.fir                     | 27 +++++
 flang/test/Lower/OpenACC/acc-cache.f90        |  5 +-
 .../Lower/OpenMP/hlfir-seqloop-parallel.f90   | 64 ++++++------
 .../OpenMP/parallel-private-clause-fixes.f90  | 26 ++---
 .../OpenMP/sections-predetermined-private.f90 | 36 ++++---
 flang/test/Lower/OpenMP/shared-loop.f90       | 54 +++++-----
 ...oop-reduction-allocatable-array-minmax.f90 | 26 ++---
 flang/test/Lower/OpenMP/wsloop-variable.f90   | 24 ++---
 .../do_concurrent_loop_in_nested_block.f90    |  5 +-
 flang/test/Lower/do_loop.f90                  | 98 +++++++++----------
 flang/test/Lower/do_loop_unstructured.f90     | 14 +--
 flang/test/Lower/infinite_loop.f90            | 22 +++--
 flang/test/Lower/loops2.f90                   | 34 ++++---
 flang/test/Lower/mixed_loops.f90              | 20 ++--
 flang/test/Lower/nsw.f90                      | 16 +--
 .../DoConcurrent/skip_all_nested_loops.f90    |  7 +-
 23 files changed, 394 insertions(+), 265 deletions(-)

diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index df7fdb27586d9..78be358d0f97f 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -2468,6 +2468,7 @@ class region_Op<string mnemonic, list<Trait> traits = []> :
 }
 
 def fir_DoLoopOp : region_Op<"do_loop", [AttrSizedOperandSegments,
+    AllTypesMatch<["lowerBound", "upperBound", "step"]>,
     DeclareOpInterfaceMethods<LoopLikeOpInterface,
         ["getYieldedValuesMutable"]>,
     DeclareOpInterfaceMethods<RegionBranchOpInterface,
@@ -2475,7 +2476,8 @@ def fir_DoLoopOp : region_Op<"do_loop", [AttrSizedOperandSegments,
   let summary = "generalized loop operation";
   let description = [{
     Generalized high-level looping construct. This operation is similar to
-    MLIR's `scf.for`.
+    MLIR's `scf.for`. The bounds, step, and induction variable have the same
+    signless integer or index type.
 
     ```
       %l = arith.constant 0 : index
@@ -2497,9 +2499,9 @@ def fir_DoLoopOp : region_Op<"do_loop", [AttrSizedOperandSegments,
   let hasCustomAssemblyFormat = 1;
 
   let arguments = (ins
-    Index:$lowerBound,
-    Index:$upperBound,
-    Index:$step,
+    AnySignlessIntegerOrIndex:$lowerBound,
+    AnySignlessIntegerOrIndex:$upperBound,
+    AnySignlessIntegerOrIndex:$step,
     Variadic<AnyType>:$reduceOperands,
     Variadic<AnyType>:$initArgs,
     OptionalAttr<UnitAttr>:$unordered,
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index d5b9cef8d4ca4..8e7827b5e0b44 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2815,8 +2815,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                               const IncrementLoopInfo &info,
                               bool *isConst = nullptr) {
     mlir::Location loc = toLocation();
-    mlir::Type controlType = info.isStructured() ? builder->getIndexType()
-                                                 : info.getLoopVariableType();
+    mlir::Type controlType = info.isStructured() && info.isConcurrent
+                                 ? builder->getIndexType()
+                                 : info.getLoopVariableType();
     Fortran::lower::StatementContext stmtCtx;
     if (expr) {
       if (isConst)
@@ -3047,9 +3048,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         if (genDoConcurrent)
           continue;
 
-        // The loop variable is a doLoop op argument.
-        mlir::Type loopVarType = info.getLoopVariableType();
-
         // Lower the loop without the secondary-induction iter_arg so memory
         // recurrences (e.g. reductions) stay visible to later analyses. The DO
         // variable is recomputed from the induction variable in the body; its
@@ -3060,9 +3058,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
             /*iterArgs=*/mlir::ValueRange{});
         info.loopOp = loopOp;
         builder->setInsertionPointToStart(loopOp.getBody());
-        mlir::Value loopValue =
-            builder->createConvert(loc, loopVarType, loopOp.getInductionVar());
-        fir::StoreOp::create(*builder, loc, loopValue, info.loopVariable);
+        fir::StoreOp::create(*builder, loc, loopOp.getInductionVar(),
+                             info.loopVariable);
         addLoopAnnotationAttr(info, dirs);
         continue;
       }
@@ -3211,10 +3208,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         // range-extreme loops.
         auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp);
         builder->setInsertionPointAfter(doLoopOp);
-        mlir::Value lb = doLoopOp.getLowerBound();
-        mlir::Value ub = doLoopOp.getUpperBound();
-        mlir::Value st = doLoopOp.getStep();
-        mlir::Type idxTy = lb.getType();
+        mlir::Type idxTy = builder->getIndexType();
+        mlir::Value lb =
+            builder->createConvert(loc, idxTy, doLoopOp.getLowerBound());
+        mlir::Value ub =
+            builder->createConvert(loc, idxTy, doLoopOp.getUpperBound());
+        mlir::Value st = builder->createConvert(loc, idxTy, doLoopOp.getStep());
         mlir::Value zero = builder->createIntegerConstant(loc, idxTy, 0);
         mlir::Value trip = mlir::arith::SubIOp::create(*builder, loc, ub, lb);
         trip = mlir::arith::AddIOp::create(*builder, loc, trip, st);
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 38c662fb23a99..83495912f06c2 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -3782,7 +3782,7 @@ void fir::DoLoopOp::build(mlir::OpBuilder &builder,
                           {1, 1, 1, static_cast<int32_t>(reduceOperands.size()),
                            static_cast<int32_t>(iterArgs.size())}));
   if (finalCountValue) {
-    result.addTypes(builder.getIndexType());
+    result.addTypes(lb.getType());
     result.addAttribute(getFinalValueAttrName(result.name),
                         builder.getUnitAttr());
   }
@@ -3792,7 +3792,7 @@ void fir::DoLoopOp::build(mlir::OpBuilder &builder,
   bodyRegion->push_back(new mlir::Block{});
   if (iterArgs.empty() && !finalCountValue)
     fir::DoLoopOp::ensureTerminator(*bodyRegion, builder, result.location);
-  bodyRegion->front().addArgument(builder.getIndexType(), result.location);
+  bodyRegion->front().addArgument(lb.getType(), result.location);
   bodyRegion->front().addArguments(
       iterArgs.getTypes(),
       llvm::SmallVector<mlir::Location>(iterArgs.size(), result.location));
@@ -3815,13 +3815,9 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
     return mlir::failure();
 
   // Parse loop bounds.
-  auto indexType = builder.getIndexType();
-  if (parser.parseOperand(lb) ||
-      parser.resolveOperand(lb, indexType, result.operands) ||
-      parser.parseKeyword("to") || parser.parseOperand(ub) ||
-      parser.resolveOperand(ub, indexType, result.operands) ||
-      parser.parseKeyword("step") || parser.parseOperand(step) ||
-      parser.resolveOperand(step, indexType, result.operands))
+  if (parser.parseOperand(lb) || parser.parseKeyword("to") ||
+      parser.parseOperand(ub) || parser.parseKeyword("step") ||
+      parser.parseOperand(step))
     return mlir::failure();
 
   if (mlir::succeeded(parser.parseOptionalKeyword("unordered")))
@@ -3876,9 +3872,10 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
                                 std::get<1>(operand_type), result.operands))
         return mlir::failure();
   } else if (succeeded(parser.parseOptionalArrow())) {
-    if (parser.parseKeyword("index"))
+    mlir::Type finalValueType;
+    if (parser.parseType(finalValueType))
       return mlir::failure();
-    result.types.push_back(indexType);
+    result.types.push_back(finalValueType);
     prependCount = true;
   }
 
@@ -3888,6 +3885,18 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
                           {1, 1, 1, static_cast<int32_t>(reduceOperands.size()),
                            static_cast<int32_t>(iterOperands.size())}));
 
+  mlir::Type controlType = builder.getIndexType();
+  if (succeeded(parser.parseOptionalColon()) && parser.parseType(controlType))
+    return mlir::failure();
+
+  llvm::SmallVector<mlir::Value> controlOperands;
+  if (parser.resolveOperand(lb, controlType, controlOperands) ||
+      parser.resolveOperand(ub, controlType, controlOperands) ||
+      parser.resolveOperand(step, controlType, controlOperands))
+    return mlir::failure();
+  result.operands.insert(result.operands.begin(), controlOperands.begin(),
+                         controlOperands.end());
+
   if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
     return mlir::failure();
 
@@ -3895,10 +3904,12 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
   if (prependCount)
     result.addAttribute(DoLoopOp::getFinalValueAttrName(result.name),
                         builder.getUnitAttr());
-  else
-    argTypes.push_back(indexType);
+  argTypes.push_back(controlType);
   // Loop carried variables
-  argTypes.append(result.types.begin(), result.types.end());
+  mlir::TypeRange iterArgTypes = result.types;
+  if (prependCount)
+    iterArgTypes = iterArgTypes.drop_front();
+  argTypes.append(iterArgTypes.begin(), iterArgTypes.end());
   // Parse the body region.
   auto *body = result.addRegion();
   if (regionArgs.size() != argTypes.size())
@@ -3930,10 +3941,9 @@ llvm::LogicalResult fir::DoLoopOp::verify() {
   // Check that the body defines as single block argument for the induction
   // variable.
   auto *body = getBody();
-  if (!body->getArgument(0).getType().isIndex())
-    return emitOpError(
-        "expected body first argument to be an index argument for "
-        "the induction variable");
+  if (body->getArgument(0).getType() != getLowerBound().getType())
+    return emitOpError("expected induction variable to have the same type as "
+                       "the loop control");
 
   auto opNumResults = getNumResults();
   if (opNumResults == 0)
@@ -3942,6 +3952,9 @@ llvm::LogicalResult fir::DoLoopOp::verify() {
   if (getFinalValue()) {
     if (getUnordered())
       return emitOpError("unordered loop has no final value");
+    if (getResult(0).getType() != getLowerBound().getType())
+      return emitOpError("expected final value to have the same type as the "
+                         "loop control");
     opNumResults--;
   }
   if (getNumIterOperands() != opNumResults)
@@ -4001,6 +4014,8 @@ void fir::DoLoopOp::print(mlir::OpAsmPrinter &p) {
     p << " -> " << getResultTypes();
     printBlockTerminators = true;
   }
+  if (!getInductionVar().getType().isIndex())
+    p << " : " << getInductionVar().getType();
   p.printOptionalAttrDictWithKeyword(
       (*this)->getAttrs(),
       {"unordered", "finalValue", "reduceAttrs", "operandSegmentSizes"});
diff --git a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp
index 6eaee27cf7cbe..a539411373084 100644
--- a/flang/lib/Optimizer/Transforms/AffinePromotion.cpp
+++ b/flang/lib/Optimizer/Transforms/AffinePromotion.cpp
@@ -117,6 +117,8 @@ struct AffineLoopAnalysis {
   bool analyzeLoop(fir::DoLoopOp loopOperation,
                    AffineFunctionAnalysis &functionAnalysis) {
     LLVM_DEBUG(llvm::dbgs() << "AffineLoopAnalysis: \n"; loopOperation.dump(););
+    if (!loopOperation.getLowerBound().getType().isIndex())
+      return false;
     return analyzeMemoryAccess(loopOperation) &&
            analysisResults(loopOperation) &&
            analyzeBody(loopOperation, functionAnalysis);
diff --git a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp
index 72fd50467b3f9..fefee609d817f 100644
--- a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp
+++ b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp
@@ -78,10 +78,19 @@ class CfgLoopConv : public mlir::OpRewritePattern<fir::DoLoopOp> {
 
     // Initalization block
     rewriter.setInsertionPointToEnd(initBlock);
-    auto diff = mlir::arith::SubIOp::create(rewriter, loc, high, low);
-    auto distance = mlir::arith::AddIOp::create(rewriter, loc, diff, step);
+    auto toIndex = [&](mlir::Value value) -> mlir::Value {
+      if (value.getType().isIndex())
+        return value;
+      return fir::ConvertOp::create(rewriter, loc, rewriter.getIndexType(),
+                                    value);
+    };
+    mlir::Value lowIndex = toIndex(low);
+    mlir::Value highIndex = toIndex(high);
+    mlir::Value stepIndex = toIndex(step);
+    auto diff = mlir::arith::SubIOp::create(rewriter, loc, highIndex, lowIndex);
+    auto distance = mlir::arith::AddIOp::create(rewriter, loc, diff, stepIndex);
     mlir::Value iters =
-        mlir::arith::DivSIOp::create(rewriter, loc, distance, step);
+        mlir::arith::DivSIOp::create(rewriter, loc, distance, stepIndex);
 
     if (forceLoopToExecuteOnce) {
       auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0);
diff --git a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
index 53ef7163f6b53..477371c1e7385 100644
--- a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
@@ -47,8 +47,9 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
     mlir::Value high = doLoopOp.getUpperBound();
     assert(low && high && "must be a Value");
     mlir::Value step = doLoopOp.getStep();
+    bool hasTypedIV = !low.getType().isIndex();
     mlir::SmallVector<mlir::Value> iterArgs;
-    if (hasFinalValue)
+    if (hasTypedIV || hasFinalValue)
       iterArgs.push_back(low);
     iterArgs.append(doLoopOp.getIterOperands().begin(),
                     doLoopOp.getIterOperands().end());
@@ -58,16 +59,25 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
     // must be a positive value.
     // For easier conversion, we calculate the trip count and use a canonical
     // induction variable.
-    auto diff = mlir::arith::SubIOp::create(rewriter, loc, high, low);
-    auto distance = mlir::arith::AddIOp::create(rewriter, loc, diff, step);
+    auto toIndex = [&](mlir::Value value) -> mlir::Value {
+      if (value.getType().isIndex())
+        return value;
+      return fir::ConvertOp::create(rewriter, loc, rewriter.getIndexType(),
+                                    value);
+    };
+    mlir::Value lowIndex = toIndex(low);
+    mlir::Value highIndex = toIndex(high);
+    mlir::Value stepIndex = toIndex(step);
+    auto diff = mlir::arith::SubIOp::create(rewriter, loc, highIndex, lowIndex);
+    auto distance = mlir::arith::AddIOp::create(rewriter, loc, diff, stepIndex);
     auto tripCount =
-        mlir::arith::DivSIOp::create(rewriter, loc, distance, step);
+        mlir::arith::DivSIOp::create(rewriter, loc, distance, stepIndex);
     auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0);
     auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1);
 
     // Create the scf.for or scf.parallel operation
     mlir::Operation *scfLoopOp = nullptr;
-    if (isUnordered && parallelUnorderedLoop) {
+    if (isUnordered && parallelUnorderedLoop && !hasTypedIV) {
       scfLoopOp = mlir::scf::ParallelOp::create(rewriter, loc, {zero},
                                                 {tripCount}, {one}, iterArgs);
     } else {
@@ -88,14 +98,21 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
                                        std::prev(loopOps.end()));
 
     rewriter.setInsertionPointToStart(&scfLoopBody);
-    mlir::Value iv = mlir::arith::MulIOp::create(
-        rewriter, loc, scfLoopLikeOp.getSingleInductionVar().value(), step);
-    iv = mlir::arith::AddIOp::create(rewriter, loc, low, iv);
+    mlir::Value iv;
+    if (hasTypedIV) {
+      iv = scfLoopLikeOp.getRegionIterArgs().front();
+    } else {
+      iv = mlir::arith::MulIOp::create(
+          rewriter, loc, scfLoopLikeOp.getSingleInductionVar().value(), step);
+      iv = mlir::arith::AddIOp::create(rewriter, loc, low, iv);
+    }
     mlir::Value firIV = doLoopOp.getInductionVar();
     firIV.replaceAllUsesWith(iv);
 
     mlir::Value finalValue;
-    if (hasFinalValue) {
+    if (hasTypedIV) {
+      finalValue = mlir::arith::AddIOp::create(rewriter, loc, iv, step);
+    } else if (hasFinalValue) {
       // Prefer re-using an existing `arith.addi` in the moved loop body if it
       // already computes the next `iv + step`.
       if (!results.empty()) {
@@ -110,21 +127,23 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
         finalValue = mlir::arith::AddIOp::create(rewriter, loc, iv, step);
     }
 
-    if (hasFinalValue || !results.empty()) {
+    if (hasTypedIV || hasFinalValue || !results.empty()) {
       rewriter.setInsertionPointToEnd(&scfLoopBody);
       llvm::SmallVector<mlir::Value> yieldOperands;
-      if (hasFinalValue) {
+      if (hasTypedIV || hasFinalValue) {
         yieldOperands.push_back(finalValue);
+      }
+      if (hasFinalValue)
         llvm::append_range(yieldOperands, results.drop_front());
-      } else {
+      else
         llvm::append_range(yieldOperands, results);
-      }
       mlir::scf::YieldOp::create(rewriter, resultOp->getLoc(), yieldOperands);
     }
     rewriter.replaceAllUsesWith(
         doLoopOp.getRegionIterArgs(),
-        hasFinalValue ? scfLoopLikeOp.getRegionIterArgs().drop_front()
-                      : scfLoopLikeOp.getRegionIterArgs());
+        hasTypedIV || hasFinalValue
+            ? scfLoopLikeOp.getRegionIterArgs().drop_front()
+            : scfLoopLikeOp.getRegionIterArgs());
 
     // Copy loop annotations from the fir.do_loop to scf loop op.
     if (auto ann = doLoopOp.getLoopAnnotation())
@@ -135,7 +154,10 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
     if (auto parDims = doLoopOp->getAttr(mlir::acc::GPUParallelDimsAttr::name))
       scfLoopOp->setAttr(mlir::acc::GPUParallelDimsAttr::name, parDims);
 
-    rewriter.replaceOp(doLoopOp, scfLoopOp);
+    mlir::ValueRange scfResults = scfLoopOp->getResults();
+    if (hasTypedIV && !hasFinalValue)
+      scfResults = scfResults.drop_front();
+    rewriter.replaceOp(doLoopOp, scfResults);
     return mlir::success();
   }
 
diff --git a/flang/test/Fir/FirToSCF/do-loop.fir b/flang/test/Fir/FirToSCF/do-loop.fir
index 8883d795b5d2d..f81dbfc52015c 100644
--- a/flang/test/Fir/FirToSCF/do-loop.fir
+++ b/flang/test/Fir/FirToSCF/do-loop.fir
@@ -34,6 +34,32 @@ func.func @simple_loop(%arg0: !fir.ref<!fir.array<100xi32>>) {
 
 // -----
 
+// CHECK-LABEL: func.func @typed_loop(
+// CHECK-SAME: %[[LB:.*]]: i32, %[[UB:.*]]: i32, %[[STEP:.*]]: i32,
+// CHECK-SAME: %[[ADDR:.*]]: !fir.ref<i32>) {
+// CHECK: %[[LB_IDX:.*]] = fir.convert %[[LB]] : (i32) -> index
+// CHECK: %[[UB_IDX:.*]] = fir.convert %[[UB]] : (i32) -> index
+// CHECK: %[[STEP_IDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
+// CHECK: %[[DIFF:.*]] = arith.subi %[[UB_IDX]], %[[LB_IDX]] : index
+// CHECK: %[[DISTANCE:.*]] = arith.addi %[[DIFF]], %[[STEP_IDX]] : index
+// CHECK: %[[TRIP:.*]] = arith.divsi %[[DISTANCE]], %[[STEP_IDX]] : index
+// CHECK: %[[C0:.*]] = arith.constant 0 : index
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: scf.for %{{.*}} = %[[C0]] to %[[TRIP]] step %[[C1]] iter_args(%[[IV:.*]] = %[[LB]]) -> (i32) {
+// CHECK:   %[[NEXT:.*]] = arith.addi %[[IV]], %[[STEP]] : i32
+// CHECK:   fir.store %[[IV]] to %[[ADDR]] : !fir.ref<i32>
+// CHECK:   scf.yield %[[NEXT]] : i32
+// CHECK: }
+func.func @typed_loop(%lb: i32, %ub: i32, %step: i32,
+                      %addr: !fir.ref<i32>) {
+  fir.do_loop %iv = %lb to %ub step %step : i32 {
+    fir.store %iv to %addr : !fir.ref<i32>
+  }
+  return
+}
+
+// -----
+
 // CHECK-LABEL:   func.func @loop_with_negtive_step(
 // CHECK-SAME:      %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>) {
 // CHECK:           %[[VAL_0:.*]] = arith.constant 100 : index
diff --git a/flang/test/Fir/loop01.fir b/flang/test/Fir/loop01.fir
index 30d10b9bbdb97..038626932829c 100644
--- a/flang/test/Fir/loop01.fir
+++ b/flang/test/Fir/loop01.fir
@@ -48,6 +48,33 @@ func.func private @f2() -> i1
 
 // -----
 
+func.func @typed_loop(%lo: i32, %up: i32, %step: i32,
+                      %addr: !fir.ref<i32>) {
+  fir.do_loop %iv = %lo to %up step %step : i32 {
+    fir.store %iv to %addr : !fir.ref<i32>
+  }
+  return
+}
+
+// CHECK-LABEL: func @typed_loop(
+// CHECK-SAME: %[[LO:.*]]: i32, %[[UP:.*]]: i32, %[[STEP:.*]]: i32,
+// CHECK-SAME: %[[ADDR:.*]]: !fir.ref<i32>) {
+// CHECK: %[[LO_IDX:.*]] = fir.convert %[[LO]] : (i32) -> index
+// CHECK: %[[UP_IDX:.*]] = fir.convert %[[UP]] : (i32) -> index
+// CHECK: %[[STEP_IDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
+// CHECK: %[[DIFF:.*]] = arith.subi %[[UP_IDX]], %[[LO_IDX]] : index
+// CHECK: %[[DISTANCE:.*]] = arith.addi %[[DIFF]], %[[STEP_IDX]] : index
+// CHECK: %[[TRIP:.*]] = arith.divsi %[[DISTANCE]], %[[STEP_IDX]] : index
+// CHECK: br ^bb1(%[[LO]], %[[TRIP]] : i32, index)
+// CHECK: ^bb1(%[[IV:.*]]: i32, %[[COUNT:.*]]: index):
+// CHECK: fir.store %[[IV]] to %[[ADDR]] : !fir.ref<i32>
+// CHECK: %[[NEXT:.*]] = arith.addi %[[IV]], %[[STEP]] overflow<nsw> : i32
+// CHECK: %[[ONE:.*]] = arith.constant 1 : index
+// CHECK: %[[COUNT_NEXT:.*]] = arith.subi %[[COUNT]], %[[ONE]] : index
+// CHECK: br ^bb1(%[[NEXT]], %[[COUNT_NEXT]] : i32, index)
+
+// -----
+
 func.func @x2(%lo : index, %up : index, %ok : i1) {
   %c1 = arith.constant 1 : index
   %unused = fir.iterate_while (%i = %lo to %up step %c1) and (%ok1 = %ok) {
diff --git a/flang/test/Lower/OpenACC/acc-cache.f90 b/flang/test/Lower/OpenACC/acc-cache.f90
index 03e06467f694d..17fc445be8d04 100644
--- a/flang/test/Lower/OpenACC/acc-cache.f90
+++ b/flang/test/Lower/OpenACC/acc-cache.f90
@@ -242,10 +242,9 @@ subroutine test_cache_2d_loop_vars()
 ! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtest_cache_2d_loop_varsEi"}
 ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
 ! Inner loop j (non-acc loop, fir.do_loop)
-! CHECK: fir.do_loop %[[J_IV:.*]] = {{.*}} to {{.*}} step {{.*}} {
+! CHECK: fir.do_loop %[[J_IV:.*]] = {{.*}} to {{.*}} step {{.*}} : i32 {
 ! Inner loop iterator j is stored to j variable
-! CHECK: %[[J_CONV:.*]] = fir.convert %[[J_IV]] : (index) -> i32
-! CHECK: fir.store %[[J_CONV]] to %[[J_REF:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[J_IV]] to %[[J_REF:.*]] : !fir.ref<i32>
 ! Dimension 1 bounds from j: lowerbound = j-1, upperbound = j
 ! CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index)
 ! Dimension 2 bounds from i: lowerbound = i-1, upperbound = i
diff --git a/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90 b/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
index 802a5fe18e6dd..9f0c1974efcb4 100644
--- a/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
+++ b/flang/test/Lower/OpenMP/hlfir-seqloop-parallel.f90
@@ -22,18 +22,20 @@ subroutine sb1
 !CHECK:    %[[I_DECL:.*]]:2 = hlfir.declare %[[I_ADDR]] {uniq_name = "_QFsb1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 !CHECK:    omp.parallel private({{.*}} %[[I_DECL]]#0 -> %[[I_PVT_ADDR:.*]] : {{.*}}) {
 !CHECK:      %[[I_PVT_DECL:.*]]:2 = hlfir.declare %[[I_PVT_ADDR]] {uniq_name = "_QFsb1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
-!CHECK:      fir.do_loop %{{.*}} = %[[I_LB:.*]] to %[[I_UB:.*]] step %[[I_ST:.*]] {
-!CHECK:        %[[I_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      fir.do_loop %[[I_VAL:.*]] = %[[I_LB:.*]] to %[[I_UB:.*]] step %[[I_ST:.*]] : i32 {
 !CHECK:        fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      }
+!CHECK:      %[[I_LB_IDX:.*]] = fir.convert %[[I_LB]] : (i32) -> index
+!CHECK:      %[[I_UB_IDX:.*]] = fir.convert %[[I_UB]] : (i32) -> index
+!CHECK:      %[[I_ST_IDX:.*]] = fir.convert %[[I_ST]] : (i32) -> index
 !CHECK:      %[[I_C0:.*]] = arith.constant 0 : index
-!CHECK:      %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] : index
-!CHECK:      %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] : index
-!CHECK:      %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : index
+!CHECK:      %[[I_D:.*]] = arith.subi %[[I_UB_IDX]], %[[I_LB_IDX]] : index
+!CHECK:      %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST_IDX]] : index
+!CHECK:      %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST_IDX]] : index
 !CHECK:      %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : index
 !CHECK:      %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : index
-!CHECK:      %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] : index
-!CHECK:      %[[I_IDX:.*]] = arith.addi %[[I_LB]], %[[I_M]] : index
+!CHECK:      %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST_IDX]] : index
+!CHECK:      %[[I_IDX:.*]] = arith.addi %[[I_LB_IDX]], %[[I_M]] : index
 !CHECK:      %[[I_FINAL_VAL:.*]] = fir.convert %[[I_IDX]] : (index) -> i32
 !CHECK:      fir.store %[[I_FINAL_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      omp.terminator
@@ -68,48 +70,54 @@ subroutine sb2
 
 !CHECK:      %[[I_PVT_DECL:.*]]:2 = hlfir.declare %[[I_PVT_ADDR]] {uniq_name = "_QFsb2Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 
-!CHECK:      fir.do_loop %{{.*}} = %[[J_LB:.*]] to %[[J_UB:.*]] step %[[J_ST:.*]] {
-!CHECK:        %[[J_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:      fir.do_loop %[[J_VAL:.*]] = %[[J_LB:.*]] to %[[J_UB:.*]] step %[[J_ST:.*]] : i32 {
 !CHECK:        fir.store %[[J_VAL]] to %[[J_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        fir.if %{{.*}} {
-!CHECK:          fir.do_loop %{{.*}} = %[[I_LB:.*]] to %[[I_UB:.*]] step %[[I_ST:.*]] {
-!CHECK:            %[[I_VAL:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:          fir.do_loop %[[I_VAL:.*]] = %[[I_LB:.*]] to %[[I_UB:.*]] step %[[I_ST:.*]] : i32 {
 !CHECK:            fir.store %[[I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:          }
+!CHECK:          %[[I_LB_IDX:.*]] = fir.convert %[[I_LB]] : (i32) -> index
+!CHECK:          %[[I_UB_IDX:.*]] = fir.convert %[[I_UB]] : (i32) -> index
+!CHECK:          %[[I_ST_IDX:.*]] = fir.convert %[[I_ST]] : (i32) -> index
 !CHECK:          %[[I_C0:.*]] = arith.constant 0 : index
-!CHECK:          %[[I_D:.*]] = arith.subi %[[I_UB]], %[[I_LB]] : index
-!CHECK:          %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST]] : index
-!CHECK:          %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST]] : index
+!CHECK:          %[[I_D:.*]] = arith.subi %[[I_UB_IDX]], %[[I_LB_IDX]] : index
+!CHECK:          %[[I_A:.*]] = arith.addi %[[I_D]], %[[I_ST_IDX]] : index
+!CHECK:          %[[I_TR:.*]] = arith.divsi %[[I_A]], %[[I_ST_IDX]] : index
 !CHECK:          %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TR]], %[[I_C0]] : index
 !CHECK:          %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TR]] : index
-!CHECK:          %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST]] : index
-!CHECK:          %[[I_IDX:.*]] = arith.addi %[[I_LB]], %[[I_M]] : index
+!CHECK:          %[[I_M:.*]] = arith.muli %[[I_SEL]], %[[I_ST_IDX]] : index
+!CHECK:          %[[I_IDX:.*]] = arith.addi %[[I_LB_IDX]], %[[I_M]] : index
 !CHECK:          %[[FINAL_I_VAL:.*]] = fir.convert %[[I_IDX]] : (index) -> i32
 !CHECK:          fir.store %[[FINAL_I_VAL]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        }
-!CHECK:        fir.do_loop %{{.*}} = %[[I2_LB:.*]] to %[[I2_UB:.*]] step %[[I2_ST:.*]] {
-!CHECK:          %[[I_VAL2:.*]] = fir.convert %{{.*}} : (index) -> i32
+!CHECK:        fir.do_loop %[[I_VAL2:.*]] = %[[I2_LB:.*]] to %[[I2_UB:.*]] step %[[I2_ST:.*]] : i32 {
 !CHECK:          fir.store %[[I_VAL2]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:        }
+!CHECK:        %[[I2_LB_IDX:.*]] = fir.convert %[[I2_LB]] : (i32) -> index
+!CHECK:        %[[I2_UB_IDX:.*]] = fir.convert %[[I2_UB]] : (i32) -> index
+!CHECK:        %[[I2_ST_IDX:.*]] = fir.convert %[[I2_ST]] : (i32) -> index
 !CHECK:        %[[I2_C0:.*]] = arith.constant 0 : index
-!CHECK:        %[[I2_D:.*]] = arith.subi %[[I2_UB]], %[[I2_LB]] : index
-!CHECK:        %[[I2_A:.*]] = arith.addi %[[I2_D]], %[[I2_ST]] : index
-!CHECK:        %[[I2_TR:.*]] = arith.divsi %[[I2_A]], %[[I2_ST]] : index
+!CHECK:        %[[I2_D:.*]] = arith.subi %[[I2_UB_IDX]], %[[I2_LB_IDX]] : index
+!CHECK:        %[[I2_A:.*]] = arith.addi %[[I2_D]], %[[I2_ST_IDX]] : index
+!CHECK:        %[[I2_TR:.*]] = arith.divsi %[[I2_A]], %[[I2_ST_IDX]] : index
 !CHECK:        %[[I2_CMP:.*]] = arith.cmpi slt, %[[I2_TR]], %[[I2_C0]] : index
 !CHECK:        %[[I2_SEL:.*]] = arith.select %[[I2_CMP]], %[[I2_C0]], %[[I2_TR]] : index
-!CHECK:        %[[I2_M:.*]] = arith.muli %[[I2_SEL]], %[[I2_ST]] : index
-!CHECK:        %[[I2_IDX:.*]] = arith.addi %[[I2_LB]], %[[I2_M]] : index
+!CHECK:        %[[I2_M:.*]] = arith.muli %[[I2_SEL]], %[[I2_ST_IDX]] : index
+!CHECK:        %[[I2_IDX:.*]] = arith.addi %[[I2_LB_IDX]], %[[I2_M]] : index
 !CHECK:        %[[FINAL_I_VAL2:.*]] = fir.convert %[[I2_IDX]] : (index) -> i32
 !CHECK:        fir.store %[[FINAL_I_VAL2]] to %[[I_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      }
+!CHECK:      %[[J_LB_IDX:.*]] = fir.convert %[[J_LB]] : (i32) -> index
+!CHECK:      %[[J_UB_IDX:.*]] = fir.convert %[[J_UB]] : (i32) -> index
+!CHECK:      %[[J_ST_IDX:.*]] = fir.convert %[[J_ST]] : (i32) -> index
 !CHECK:      %[[J_C0:.*]] = arith.constant 0 : index
-!CHECK:      %[[J_D:.*]] = arith.subi %[[J_UB]], %[[J_LB]] : index
-!CHECK:      %[[J_A:.*]] = arith.addi %[[J_D]], %[[J_ST]] : index
-!CHECK:      %[[J_TR:.*]] = arith.divsi %[[J_A]], %[[J_ST]] : index
+!CHECK:      %[[J_D:.*]] = arith.subi %[[J_UB_IDX]], %[[J_LB_IDX]] : index
+!CHECK:      %[[J_A:.*]] = arith.addi %[[J_D]], %[[J_ST_IDX]] : index
+!CHECK:      %[[J_TR:.*]] = arith.divsi %[[J_A]], %[[J_ST_IDX]] : index
 !CHECK:      %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TR]], %[[J_C0]] : index
 !CHECK:      %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TR]] : index
-!CHECK:      %[[J_M:.*]] = arith.muli %[[J_SEL]], %[[J_ST]] : index
-!CHECK:      %[[J_IDX:.*]] = arith.addi %[[J_LB]], %[[J_M]] : index
+!CHECK:      %[[J_M:.*]] = arith.muli %[[J_SEL]], %[[J_ST_IDX]] : index
+!CHECK:      %[[J_IDX:.*]] = arith.addi %[[J_LB_IDX]], %[[J_M]] : index
 !CHECK:      %[[FINAL_J_VAL:.*]] = fir.convert %[[J_IDX]] : (index) -> i32
 !CHECK:      fir.store %[[FINAL_J_VAL]] to %[[J_PVT_DECL]]#0 : !fir.ref<i32>
 !CHECK:      omp.terminator
diff --git a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
index f1f2c2d2ba7e3..38a42fed442c1 100644
--- a/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
+++ b/flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90
@@ -53,27 +53,27 @@
 ! CHECK-DAG:           %[[PRIV_J_DECL:.*]]:2 = hlfir.declare %[[PRIV_J]] {uniq_name = "_QFmultiple_private_fixEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 ! CHECK-DAG:           %[[PRIV_X_DECL:.*]]:2 = hlfir.declare %[[PRIV_X]] {uniq_name = "_QFmultiple_private_fixEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 ! CHECK:               hlfir.assign %[[VAL_6]] to %[[PRIV_I_DECL]]#0 : i32, !fir.ref<i32>
-! CHECK:               %[[VAL_7:.*]] = arith.constant 1 : i32
-! CHECK:               %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> index
-! CHECK:               %[[VAL_9:.*]] = fir.load %[[GAMA_DECL]]#0 : !fir.ref<i32>
-! CHECK:               %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index
-! CHECK:               %[[VAL_11:.*]] = arith.constant 1 : index
-! CHECK:               fir.do_loop %[[VAL_13:[^ ]*]] = %[[VAL_8]] to %[[VAL_10]] step %[[VAL_11]] {
-! CHECK:                 %[[IV:.*]] = fir.convert %[[VAL_13]] : (index) -> i32
-! CHECK:                 fir.store %[[IV]] to %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
+! CHECK:               %[[VAL_8:.*]] = arith.constant 1 : i32
+! CHECK:               %[[VAL_10:.*]] = fir.load %[[GAMA_DECL]]#0 : !fir.ref<i32>
+! CHECK:               %[[VAL_11:.*]] = arith.constant 1 : i32
+! CHECK:               fir.do_loop %[[VAL_13:[^ ]*]] = %[[VAL_8]] to %[[VAL_10]] step %[[VAL_11]] : i32 {
+! CHECK:                 fir.store %[[VAL_13]] to %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:                 %[[LOAD:.*]] = fir.load %[[PRIV_I_DECL]]#0 : !fir.ref<i32>
 ! CHECK:                 %[[VAL_15:.*]] = fir.load %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:                 %[[VAL_16:.*]] = arith.addi %[[LOAD]], %[[VAL_15]] : i32
 ! CHECK:                 hlfir.assign %[[VAL_16]] to %[[PRIV_X_DECL]]#0 : i32, !fir.ref<i32>
 ! CHECK:               }
+! CHECK:               %[[VAL_8_IDX:.*]] = fir.convert %[[VAL_8]] : (i32) -> index
+! CHECK:               %[[VAL_10_IDX:.*]] = fir.convert %[[VAL_10]] : (i32) -> index
+! CHECK:               %[[VAL_11_IDX:.*]] = fir.convert %[[VAL_11]] : (i32) -> index
 ! CHECK:               %[[C0:.*]] = arith.constant 0 : index
-! CHECK:               %[[DIFF:.*]] = arith.subi %[[VAL_10]], %[[VAL_8]] : index
-! CHECK:               %[[ADD:.*]] = arith.addi %[[DIFF]], %[[VAL_11]] : index
-! CHECK:               %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[VAL_11]] : index
+! CHECK:               %[[DIFF:.*]] = arith.subi %[[VAL_10_IDX]], %[[VAL_8_IDX]] : index
+! CHECK:               %[[ADD:.*]] = arith.addi %[[DIFF]], %[[VAL_11_IDX]] : index
+! CHECK:               %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[VAL_11_IDX]] : index
 ! CHECK:               %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
 ! CHECK:               %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-! CHECK:               %[[MUL:.*]] = arith.muli %[[SEL]], %[[VAL_11]] : index
-! CHECK:               %[[IDX:.*]] = arith.addi %[[VAL_8]], %[[MUL]] : index
+! CHECK:               %[[MUL:.*]] = arith.muli %[[SEL]], %[[VAL_11_IDX]] : index
+! CHECK:               %[[IDX:.*]] = arith.addi %[[VAL_8_IDX]], %[[MUL]] : index
 ! CHECK:               %[[VAL_12:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:               fir.store %[[VAL_12]] to %[[PRIV_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:               omp.yield
diff --git a/flang/test/Lower/OpenMP/sections-predetermined-private.f90 b/flang/test/Lower/OpenMP/sections-predetermined-private.f90
index 66de7359c42bf..95a7cdc7b653d 100644
--- a/flang/test/Lower/OpenMP/sections-predetermined-private.f90
+++ b/flang/test/Lower/OpenMP/sections-predetermined-private.f90
@@ -15,35 +15,39 @@
 ! CHECK:             %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
 ! CHECK:             omp.sections {
 ! CHECK:               omp.section {
-! CHECK:                 fir.do_loop %[[VAL_12:.*]] = %[[LB1:.*]] to %[[UB1:.*]] step %[[ST1:.*]] {
-! CHECK:                   %[[VAL_IV:.*]] = fir.convert %[[VAL_12]] : (index) -> i32
-! CHECK:                   fir.store %[[VAL_IV]] to %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:                 fir.do_loop %[[VAL_12:.*]] = %[[LB1:.*]] to %[[UB1:.*]] step %[[ST1:.*]] : i32 {
+! CHECK:                   fir.store %[[VAL_12]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 }
+! CHECK:                 %[[LB1IDX:.*]] = fir.convert %[[LB1]] : (i32) -> index
+! CHECK:                 %[[UB1IDX:.*]] = fir.convert %[[UB1]] : (i32) -> index
+! CHECK:                 %[[ST1IDX:.*]] = fir.convert %[[ST1]] : (i32) -> index
 ! CHECK:                 %[[C01:.*]] = arith.constant 0 : index
-! CHECK:                 %[[D1:.*]] = arith.subi %[[UB1]], %[[LB1]] : index
-! CHECK:                 %[[A1:.*]] = arith.addi %[[D1]], %[[ST1]] : index
-! CHECK:                 %[[TR1:.*]] = arith.divsi %[[A1]], %[[ST1]] : index
+! CHECK:                 %[[D1:.*]] = arith.subi %[[UB1IDX]], %[[LB1IDX]] : index
+! CHECK:                 %[[A1:.*]] = arith.addi %[[D1]], %[[ST1IDX]] : index
+! CHECK:                 %[[TR1:.*]] = arith.divsi %[[A1]], %[[ST1IDX]] : index
 ! CHECK:                 %[[CMP1:.*]] = arith.cmpi slt, %[[TR1]], %[[C01]] : index
 ! CHECK:                 %[[SEL1:.*]] = arith.select %[[CMP1]], %[[C01]], %[[TR1]] : index
-! CHECK:                 %[[M1:.*]] = arith.muli %[[SEL1]], %[[ST1]] : index
-! CHECK:                 %[[LAST1IDX:.*]] = arith.addi %[[LB1]], %[[M1]] : index
+! CHECK:                 %[[M1:.*]] = arith.muli %[[SEL1]], %[[ST1IDX]] : index
+! CHECK:                 %[[LAST1IDX:.*]] = arith.addi %[[LB1IDX]], %[[M1]] : index
 ! CHECK:                 %[[LAST1:.*]] = fir.convert %[[LAST1IDX]] : (index) -> i32
 ! CHECK:                 fir.store %[[LAST1]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 omp.terminator
 ! CHECK:               }
 ! CHECK:               omp.section {
-! CHECK:                 fir.do_loop %[[VAL_26:.*]] = %[[LB2:.*]] to %[[UB2:.*]] step %[[ST2:.*]] {
-! CHECK:                   %[[VAL_IV2:.*]] = fir.convert %[[VAL_26]] : (index) -> i32
-! CHECK:                   fir.store %[[VAL_IV2]] to %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:                 fir.do_loop %[[VAL_26:.*]] = %[[LB2:.*]] to %[[UB2:.*]] step %[[ST2:.*]] : i32 {
+! CHECK:                   fir.store %[[VAL_26]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 }
+! CHECK:                 %[[LB2IDX:.*]] = fir.convert %[[LB2]] : (i32) -> index
+! CHECK:                 %[[UB2IDX:.*]] = fir.convert %[[UB2]] : (i32) -> index
+! CHECK:                 %[[ST2IDX:.*]] = fir.convert %[[ST2]] : (i32) -> index
 ! CHECK:                 %[[C02:.*]] = arith.constant 0 : index
-! CHECK:                 %[[D2:.*]] = arith.subi %[[UB2]], %[[LB2]] : index
-! CHECK:                 %[[A2:.*]] = arith.addi %[[D2]], %[[ST2]] : index
-! CHECK:                 %[[TR2:.*]] = arith.divsi %[[A2]], %[[ST2]] : index
+! CHECK:                 %[[D2:.*]] = arith.subi %[[UB2IDX]], %[[LB2IDX]] : index
+! CHECK:                 %[[A2:.*]] = arith.addi %[[D2]], %[[ST2IDX]] : index
+! CHECK:                 %[[TR2:.*]] = arith.divsi %[[A2]], %[[ST2IDX]] : index
 ! CHECK:                 %[[CMP2:.*]] = arith.cmpi slt, %[[TR2]], %[[C02]] : index
 ! CHECK:                 %[[SEL2:.*]] = arith.select %[[CMP2]], %[[C02]], %[[TR2]] : index
-! CHECK:                 %[[M2:.*]] = arith.muli %[[SEL2]], %[[ST2]] : index
-! CHECK:                 %[[LAST2IDX:.*]] = arith.addi %[[LB2]], %[[M2]] : index
+! CHECK:                 %[[M2:.*]] = arith.muli %[[SEL2]], %[[ST2IDX]] : index
+! CHECK:                 %[[LAST2IDX:.*]] = arith.addi %[[LB2IDX]], %[[M2]] : index
 ! CHECK:                 %[[LAST2:.*]] = fir.convert %[[LAST2IDX]] : (index) -> i32
 ! CHECK:                 fir.store %[[LAST2]] to %[[VAL_4]]#0 : !fir.ref<i32>
 ! CHECK:                 omp.terminator
diff --git a/flang/test/Lower/OpenMP/shared-loop.f90 b/flang/test/Lower/OpenMP/shared-loop.f90
index cf6f24cc499ef..5ea4bbb0b260d 100644
--- a/flang/test/Lower/OpenMP/shared-loop.f90
+++ b/flang/test/Lower/OpenMP/shared-loop.f90
@@ -9,19 +9,21 @@
 ! CHECK:    omp.parallel {
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
-! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
-! CHECK:            fir.store %[[IV]] to %[[DECL_I]]#0
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] : i32 {
+! CHECK:            fir.store %[[ARG0]] to %[[DECL_I]]#0
 ! CHECK:            hlfir.assign
 ! CHECK:          }
+! CHECK:          %[[LBIDX:.*]] = fir.convert %[[LB]] : (i32) -> index
+! CHECK:          %[[UBIDX:.*]] = fir.convert %[[UB]] : (i32) -> index
+! CHECK:          %[[STEPIDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
 ! CHECK:          %[[C0:.*]] = arith.constant 0 : index
-! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
-! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
-! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : index
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UBIDX]], %[[LBIDX]] : index
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEPIDX]] : index
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEPIDX]] : index
 ! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
 ! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
-! CHECK:          %[[IDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEPIDX]] : index
+! CHECK:          %[[IDX:.*]] = arith.addi %[[LBIDX]], %[[MUL]] : index
 ! CHECK:          %[[LAST:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:          fir.store %[[LAST]] to %[[DECL_I]]#0
 ! CHECK:          omp.terminator
@@ -54,20 +56,22 @@ subroutine omploop
 ! CHECK:      %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
-! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] : i32 {
 ! CHECK-NOT:            fir.store %{{.*}} to %[[DECL_I]]#1
-! CHECK:            fir.store %[[IV]] to %[[DECL_PRIV_I]]#0
+! CHECK:            fir.store %[[ARG0]] to %[[DECL_PRIV_I]]#0
 ! CHECK:            hlfir.assign
 ! CHECK:          }
+! CHECK:          %[[LBIDX:.*]] = fir.convert %[[LB]] : (i32) -> index
+! CHECK:          %[[UBIDX:.*]] = fir.convert %[[UB]] : (i32) -> index
+! CHECK:          %[[STEPIDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
 ! CHECK:          %[[C0:.*]] = arith.constant 0 : index
-! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
-! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
-! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : index
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UBIDX]], %[[LBIDX]] : index
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEPIDX]] : index
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEPIDX]] : index
 ! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
 ! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
-! CHECK:          %[[IDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEPIDX]] : index
+! CHECK:          %[[IDX:.*]] = arith.addi %[[LBIDX]], %[[MUL]] : index
 ! CHECK:          %[[LAST:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:          fir.store %[[LAST]] to %[[DECL_PRIV_I]]#0
 ! CHECK:          omp.terminator
@@ -101,20 +105,22 @@ subroutine omploop2
 ! CHECK:      %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
 ! CHECK:      omp.sections {
 ! CHECK:        omp.section {
-! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
-! CHECK:            %[[IV:.*]] = fir.convert %[[ARG0]] : (index) -> i32
+! CHECK:          fir.do_loop %[[ARG0:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] : i32 {
 ! CHECK-NOT:            fir.store %{{.*}} to %[[DECL_I]]#1
-! CHECK:            fir.store %[[IV]] to %[[DECL_PRIV_I]]#0
+! CHECK:            fir.store %[[ARG0]] to %[[DECL_PRIV_I]]#0
 ! CHECK:            hlfir.assign
 ! CHECK:          }
+! CHECK:          %[[LBIDX:.*]] = fir.convert %[[LB]] : (i32) -> index
+! CHECK:          %[[UBIDX:.*]] = fir.convert %[[UB]] : (i32) -> index
+! CHECK:          %[[STEPIDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
 ! CHECK:          %[[C0:.*]] = arith.constant 0 : index
-! CHECK:          %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
-! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
-! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEP]] : index
+! CHECK:          %[[DIFF:.*]] = arith.subi %[[UBIDX]], %[[LBIDX]] : index
+! CHECK:          %[[ADDT:.*]] = arith.addi %[[DIFF]], %[[STEPIDX]] : index
+! CHECK:          %[[TRIP:.*]] = arith.divsi %[[ADDT]], %[[STEPIDX]] : index
 ! CHECK:          %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
 ! CHECK:          %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
-! CHECK:          %[[IDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK:          %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEPIDX]] : index
+! CHECK:          %[[IDX:.*]] = arith.addi %[[LBIDX]], %[[MUL]] : index
 ! CHECK:          %[[LAST:.*]] = fir.convert %[[IDX]] : (index) -> i32
 ! CHECK:          fir.store %[[LAST]] to %[[DECL_PRIV_I]]#0
 ! CHECK:          omp.terminator
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
index da0892edf6588..6a158f38419b4 100644
--- a/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-allocatable-array-minmax.f90
@@ -196,14 +196,11 @@ program reduce15
 ! CHECK:           hlfir.assign %[[VAL_34]] to %[[VAL_5]]#0 realloc : i32, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
 ! CHECK:           %[[VAL_35:.*]] = arith.constant 5 : i32
 ! CHECK:           hlfir.assign %[[VAL_35]] to %[[VAL_7]]#0 realloc : i32, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
-! CHECK:           %[[VAL_36:.*]] = arith.constant 1 : i32
-! CHECK:           %[[VAL_37:.*]] = fir.convert %[[VAL_36]] : (i32) -> index
-! CHECK:           %[[VAL_38:.*]] = arith.constant 10 : i32
-! CHECK:           %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i32) -> index
-! CHECK:           %[[VAL_40:.*]] = arith.constant 1 : index
-! CHECK:           fir.do_loop %[[VAL_43:.*]] = %[[VAL_37]] to %[[VAL_39]] step %[[VAL_40]] {
-! CHECK:             %[[VAL_44:.*]] = fir.convert %[[VAL_43]] : (index) -> i32
-! CHECK:             fir.store %[[VAL_44]] to %[[VAL_3]]#0 : !fir.ref<i32>
+! CHECK:           %[[VAL_37:.*]] = arith.constant 1 : i32
+! CHECK:           %[[VAL_39:.*]] = arith.constant 10 : i32
+! CHECK:           %[[VAL_40:.*]] = arith.constant 1 : i32
+! CHECK:           fir.do_loop %[[VAL_43:.*]] = %[[VAL_37]] to %[[VAL_39]] step %[[VAL_40]] : i32 {
+! CHECK:             fir.store %[[VAL_43]] to %[[VAL_3]]#0 : !fir.ref<i32>
 ! CHECK:             %[[VAL_45:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
 ! CHECK:             %[[VAL_46:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
 ! CHECK:             %[[VAL_47:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
@@ -211,14 +208,17 @@ program reduce15
 ! CHECK:             %[[VAL_49:.*]] = hlfir.designate %[[VAL_46]] (%[[VAL_48]])  : (!fir.box<!fir.heap<!fir.array<?xi32>>>, i64) -> !fir.ref<i32>
 ! CHECK:             hlfir.assign %[[VAL_45]] to %[[VAL_49]] : i32, !fir.ref<i32>
 ! CHECK:           }
+! CHECK:           %[[VAL_37_IDX:.*]] = fir.convert %[[VAL_37]] : (i32) -> index
+! CHECK:           %[[VAL_39_IDX:.*]] = fir.convert %[[VAL_39]] : (i32) -> index
+! CHECK:           %[[VAL_40_IDX:.*]] = fir.convert %[[VAL_40]] : (i32) -> index
 ! CHECK:           %[[VAL_C0:.*]] = arith.constant 0 : index
-! CHECK:           %[[VAL_DIFF:.*]] = arith.subi %[[VAL_39]], %[[VAL_37]] : index
-! CHECK:           %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_40]] : index
-! CHECK:           %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_40]] : index
+! CHECK:           %[[VAL_DIFF:.*]] = arith.subi %[[VAL_39_IDX]], %[[VAL_37_IDX]] : index
+! CHECK:           %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_40_IDX]] : index
+! CHECK:           %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_40_IDX]] : index
 ! CHECK:           %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : index
 ! CHECK:           %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : index
-! CHECK:           %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_40]] : index
-! CHECK:           %[[VAL_IDX:.*]] = arith.addi %[[VAL_37]], %[[VAL_MUL]] : index
+! CHECK:           %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_40_IDX]] : index
+! CHECK:           %[[VAL_IDX:.*]] = arith.addi %[[VAL_37_IDX]], %[[VAL_MUL]] : index
 ! CHECK:           %[[VAL_54:.*]] = fir.convert %[[VAL_IDX]] : (index) -> i32
 ! CHECK:           fir.store %[[VAL_54]] to %[[VAL_3]]#0 : !fir.ref<i32>
 ! CHECK:           omp.parallel {
diff --git a/flang/test/Lower/OpenMP/wsloop-variable.f90 b/flang/test/Lower/OpenMP/wsloop-variable.f90
index 155e4f7d7b700..a3f8baadfb101 100644
--- a/flang/test/Lower/OpenMP/wsloop-variable.f90
+++ b/flang/test/Lower/OpenMP/wsloop-variable.f90
@@ -133,14 +133,13 @@ subroutine wsloop_variable_sub
 !CHECK:               %[[VAL_28:.*]] = fir.convert %[[VAL_27]] : (i32) -> i16
 !CHECK:               hlfir.assign %[[VAL_28]] to %[[VAL_3]]#0 : i16, !fir.ref<i16>
 !CHECK:               %[[VAL_29:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i128>
-!CHECK:               %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i128) -> index
+!CHECK:               %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i128) -> i64
 !CHECK:               %[[VAL_31:.*]] = arith.constant 100 : i32
-!CHECK:               %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> index
+!CHECK:               %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64
 !CHECK:               %[[VAL_33:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32>
-!CHECK:               %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (i32) -> index
-!CHECK:               fir.do_loop %[[VAL_37:.*]] = %[[VAL_30]] to %[[VAL_32]] step %[[VAL_34]] {
-!CHECK:                 %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (index) -> i64
-!CHECK:                 fir.store %[[VAL_38]] to %[[VAL_17]]#0 : !fir.ref<i64>
+!CHECK:               %[[VAL_34:.*]] = fir.convert %[[VAL_33]] : (i32) -> i64
+!CHECK:               fir.do_loop %[[VAL_37:.*]] = %[[VAL_30]] to %[[VAL_32]] step %[[VAL_34]] : i64 {
+!CHECK:                 fir.store %[[VAL_37]] to %[[VAL_17]]#0 : !fir.ref<i64>
 !CHECK:                 %[[VAL_39:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i16>
 !CHECK:                 %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (i16) -> i64
 !CHECK:                 %[[VAL_41:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<i64>
@@ -148,14 +147,17 @@ subroutine wsloop_variable_sub
 !CHECK:                 %[[VAL_43:.*]] = fir.convert %[[VAL_42]] : (i64) -> f32
 !CHECK:                 hlfir.assign %[[VAL_43]] to %[[VAL_21]]#0 : f32, !fir.ref<f32>
 !CHECK:               }
+!CHECK:               %[[VAL_30_IDX:.*]] = fir.convert %[[VAL_30]] : (i64) -> index
+!CHECK:               %[[VAL_32_IDX:.*]] = fir.convert %[[VAL_32]] : (i64) -> index
+!CHECK:               %[[VAL_34_IDX:.*]] = fir.convert %[[VAL_34]] : (i64) -> index
 !CHECK:               %[[VAL_C0:.*]] = arith.constant 0 : index
-!CHECK:               %[[VAL_DIFF:.*]] = arith.subi %[[VAL_32]], %[[VAL_30]] : index
-!CHECK:               %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_34]] : index
-!CHECK:               %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_34]] : index
+!CHECK:               %[[VAL_DIFF:.*]] = arith.subi %[[VAL_32_IDX]], %[[VAL_30_IDX]] : index
+!CHECK:               %[[VAL_ADD:.*]] = arith.addi %[[VAL_DIFF]], %[[VAL_34_IDX]] : index
+!CHECK:               %[[VAL_TRIP:.*]] = arith.divsi %[[VAL_ADD]], %[[VAL_34_IDX]] : index
 !CHECK:               %[[VAL_CMP:.*]] = arith.cmpi slt, %[[VAL_TRIP]], %[[VAL_C0]] : index
 !CHECK:               %[[VAL_SEL:.*]] = arith.select %[[VAL_CMP]], %[[VAL_C0]], %[[VAL_TRIP]] : index
-!CHECK:               %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_34]] : index
-!CHECK:               %[[VAL_LAST:.*]] = arith.addi %[[VAL_30]], %[[VAL_MUL]] : index
+!CHECK:               %[[VAL_MUL:.*]] = arith.muli %[[VAL_SEL]], %[[VAL_34_IDX]] : index
+!CHECK:               %[[VAL_LAST:.*]] = arith.addi %[[VAL_30_IDX]], %[[VAL_MUL]] : index
 !CHECK:               %[[VAL_48:.*]] = fir.convert %[[VAL_LAST]] : (index) -> i64
 !CHECK:               fir.store %[[VAL_48]] to %[[VAL_17]]#0 : !fir.ref<i64>
 !CHECK:               omp.yield
diff --git a/flang/test/Lower/do_concurrent_loop_in_nested_block.f90 b/flang/test/Lower/do_concurrent_loop_in_nested_block.f90
index f498c01f3d140..9026423e94ac1 100644
--- a/flang/test/Lower/do_concurrent_loop_in_nested_block.f90
+++ b/flang/test/Lower/do_concurrent_loop_in_nested_block.f90
@@ -17,9 +17,8 @@ subroutine loop_in_nested_block
 ! CHECK:         fir.do_concurrent {
 ! CHECK:           fir.do_concurrent.loop {{.*}} local(@{{.*}} %[[OUTER_J_DECL]]#0 -> %[[LOCAL_J_ARG:.*]] : !fir.ref<i32>) {
 ! CHECK:             %[[LOCAL_J_DECL:.*]]:2 = hlfir.declare %[[LOCAL_J_ARG]]
-! CHECK:             fir.do_loop %[[NESTED_IV:.*]] = {{.*}} to {{.*}} step {{.*}} {
-! CHECK:               %[[NESTED_J:.*]] = fir.convert %[[NESTED_IV]] : (index) -> i32
-! CHECK:               fir.store %[[NESTED_J]] to %[[LOCAL_J_DECL]]#0
+! CHECK:             fir.do_loop %[[NESTED_IV:.*]] = {{.*}} to {{.*}} step {{.*}} : i32 {
+! CHECK:               fir.store %[[NESTED_IV]] to %[[LOCAL_J_DECL]]#0
 ! CHECK:             }
 ! CHECK:           }
 ! CHECK:         }
diff --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90
index 269123a8f3c4b..e4992373bcb70 100644
--- a/flang/test/Lower/do_loop.f90
+++ b/flang/test/Lower/do_loop.f90
@@ -16,23 +16,23 @@ subroutine simple_loop
   integer :: i
 
   ! CHECK: %[[C1:.*]] = arith.constant 1 : i32
-  ! CHECK: %[[C1_CVT:.*]] = fir.convert %[[C1]] : (i32) -> index
   ! CHECK: %[[C5:.*]] = arith.constant 5 : i32
-  ! CHECK: %[[C5_CVT:.*]] = fir.convert %[[C5]] : (i32) -> index
-  ! CHECK: %[[C1_STEP:.*]] = arith.constant 1 : index
-  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[C1_CVT]] to %[[C5_CVT]] step %[[C1_STEP]] {
+  ! CHECK: %[[C1_STEP:.*]] = arith.constant 1 : i32
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[C1]] to %[[C5]] step %[[C1_STEP]] : i32 {
   do i=1,5
-  ! CHECK:   %[[IV:.*]] = fir.convert %[[LI]] : (index) -> i32
-  ! CHECK:   fir.store %[[IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
+  ! CHECK:   fir.store %[[LI]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
+  ! CHECK: %[[C1_CVT:.*]] = fir.convert %[[C1]] : (i32) -> index
+  ! CHECK: %[[C5_CVT:.*]] = fir.convert %[[C5]] : (i32) -> index
+  ! CHECK: %[[C1_STEP_CVT:.*]] = fir.convert %[[C1_STEP]] : (i32) -> index
   ! CHECK: %[[C0:.*]] = arith.constant 0 : index
   ! CHECK: %[[DIFF:.*]] = arith.subi %[[C5_CVT]], %[[C1_CVT]] : index
-  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[C1_STEP]] : index
-  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[C1_STEP]] : index
+  ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[C1_STEP_CVT]] : index
+  ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[C1_STEP_CVT]] : index
   ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
   ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[C1_STEP]] : index
+  ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[C1_STEP_CVT]] : index
   ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[C1_CVT]], %[[MUL]] : index
   ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
   ! CHECK: fir.store %[[LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
@@ -56,23 +56,17 @@ subroutine nested_loop
   integer :: i, j
   asum = 0
   ! CHECK: %[[S_I:.*]] = arith.constant 1 : i32
-  ! CHECK: %[[S_I_CVT:.*]] = fir.convert %[[S_I]] : (i32) -> index
   ! CHECK: %[[E_I:.*]] = arith.constant 5 : i32
-  ! CHECK: %[[E_I_CVT:.*]] = fir.convert %[[E_I]] : (i32) -> index
-  ! CHECK: %[[ST_I:.*]] = arith.constant 1 : index
-  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S_I_CVT]] to %[[E_I_CVT]] step %[[ST_I]] {
+  ! CHECK: %[[ST_I:.*]] = arith.constant 1 : i32
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S_I]] to %[[E_I]] step %[[ST_I]] : i32 {
   do i=1,5
-    ! CHECK: %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
-    ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
+    ! CHECK: fir.store %[[LI]] to %[[I_DECL]]#0 : !fir.ref<i32>
     ! CHECK: %[[S_J:.*]] = arith.constant 1 : i32
-    ! CHECK: %[[S_J_CVT:.*]] = fir.convert %[[S_J]] : (i32) -> index
     ! CHECK: %[[E_J:.*]] = arith.constant 5 : i32
-    ! CHECK: %[[E_J_CVT:.*]] = fir.convert %[[E_J]] : (i32) -> index
-    ! CHECK: %[[ST_J:.*]] = arith.constant 1 : index
-    ! CHECK: fir.do_loop %[[LJ:[^ ]*]] = %[[S_J_CVT]] to %[[E_J_CVT]] step %[[ST_J]] {
+    ! CHECK: %[[ST_J:.*]] = arith.constant 1 : i32
+    ! CHECK: fir.do_loop %[[LJ:[^ ]*]] = %[[S_J]] to %[[E_J]] step %[[ST_J]] : i32 {
     do j=1,5
-      ! CHECK: %[[J_IV:.*]] = fir.convert %[[LJ]] : (index) -> i32
-      ! CHECK: fir.store %[[J_IV]] to %[[J_DECL]]#0 : !fir.ref<i32>
+      ! CHECK: fir.store %[[LJ]] to %[[J_DECL]]#0 : !fir.ref<i32>
       ! CHECK: %[[ASUM:.*]] = fir.load %[[ASUM_DECL]]#0 : !fir.ref<i32>
       ! CHECK: %[[I:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
       ! CHECK: %[[I_CVT:.*]] = fir.convert %[[I]] : (i32) -> i64
@@ -85,25 +79,31 @@ subroutine nested_loop
       asum = asum + arr(i,j)
     ! CHECK: }
     end do
+    ! CHECK: %[[S_J_CVT:.*]] = fir.convert %[[S_J]] : (i32) -> index
+    ! CHECK: %[[E_J_CVT:.*]] = fir.convert %[[E_J]] : (i32) -> index
+    ! CHECK: %[[ST_J_CVT:.*]] = fir.convert %[[ST_J]] : (i32) -> index
     ! CHECK: %[[J_C0:.*]] = arith.constant 0 : index
     ! CHECK: %[[J_DIFF:.*]] = arith.subi %[[E_J_CVT]], %[[S_J_CVT]] : index
-    ! CHECK: %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[ST_J]] : index
-    ! CHECK: %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[ST_J]] : index
+    ! CHECK: %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[ST_J_CVT]] : index
+    ! CHECK: %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[ST_J_CVT]] : index
     ! CHECK: %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : index
     ! CHECK: %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : index
-    ! CHECK: %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[ST_J]] : index
+    ! CHECK: %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[ST_J_CVT]] : index
     ! CHECK: %[[J_LASTIDX:.*]] = arith.addi %[[S_J_CVT]], %[[J_MUL]] : index
     ! CHECK: %[[J_LAST:.*]] = fir.convert %[[J_LASTIDX]] : (index) -> i32
     ! CHECK: fir.store %[[J_LAST]] to %[[J_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
+  ! CHECK: %[[S_I_CVT:.*]] = fir.convert %[[S_I]] : (i32) -> index
+  ! CHECK: %[[E_I_CVT:.*]] = fir.convert %[[E_I]] : (i32) -> index
+  ! CHECK: %[[ST_I_CVT:.*]] = fir.convert %[[ST_I]] : (i32) -> index
   ! CHECK: %[[I_C0:.*]] = arith.constant 0 : index
   ! CHECK: %[[I_DIFF:.*]] = arith.subi %[[E_I_CVT]], %[[S_I_CVT]] : index
-  ! CHECK: %[[I_ADD:.*]] = arith.addi %[[I_DIFF]], %[[ST_I]] : index
-  ! CHECK: %[[I_TRIP:.*]] = arith.divsi %[[I_ADD]], %[[ST_I]] : index
+  ! CHECK: %[[I_ADD:.*]] = arith.addi %[[I_DIFF]], %[[ST_I_CVT]] : index
+  ! CHECK: %[[I_TRIP:.*]] = arith.divsi %[[I_ADD]], %[[ST_I_CVT]] : index
   ! CHECK: %[[I_CMP:.*]] = arith.cmpi slt, %[[I_TRIP]], %[[I_C0]] : index
   ! CHECK: %[[I_SEL:.*]] = arith.select %[[I_CMP]], %[[I_C0]], %[[I_TRIP]] : index
-  ! CHECK: %[[I_MUL:.*]] = arith.muli %[[I_SEL]], %[[ST_I]] : index
+  ! CHECK: %[[I_MUL:.*]] = arith.muli %[[I_SEL]], %[[ST_I_CVT]] : index
   ! CHECK: %[[I_LASTIDX:.*]] = arith.addi %[[S_I_CVT]], %[[I_MUL]] : index
   ! CHECK: %[[I_LAST:.*]] = fir.convert %[[I_LASTIDX]] : (index) -> i32
   ! CHECK: fir.store %[[I_LAST]] to %[[I_DECL]]#0 : !fir.ref<i32>
@@ -117,17 +117,16 @@ subroutine down_counting_loop()
   ! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_REF]]
 
   ! CHECK: %[[C5:.*]] = arith.constant 5 : i32
-  ! CHECK: %[[C5_CVT:.*]] = fir.convert %[[C5]] : (i32) -> index
   ! CHECK: %[[C1:.*]] = arith.constant 1 : i32
-  ! CHECK: %[[C1_CVT:.*]] = fir.convert %[[C1]] : (i32) -> index
   ! CHECK: %[[CMINUS1:.*]] = arith.constant -1 : i32
-  ! CHECK: %[[CMINUS1_STEP_CVT:.*]] = fir.convert %[[CMINUS1]] : (i32) -> index
-  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[C5_CVT]] to %[[C1_CVT]] step %[[CMINUS1_STEP_CVT]] {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[C5]] to %[[C1]] step %[[CMINUS1]] : i32 {
   do i=5,1,-1
-  ! CHECK: %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
-  ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
+  ! CHECK: fir.store %[[LI]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
+  ! CHECK: %[[C5_CVT:.*]] = fir.convert %[[C5]] : (i32) -> index
+  ! CHECK: %[[C1_CVT:.*]] = fir.convert %[[C1]] : (i32) -> index
+  ! CHECK: %[[CMINUS1_STEP_CVT:.*]] = fir.convert %[[CMINUS1]] : (i32) -> index
   ! CHECK: %[[C0:.*]] = arith.constant 0 : index
   ! CHECK: %[[DIFF:.*]] = arith.subi %[[C1_CVT]], %[[C5_CVT]] : index
   ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[CMINUS1_STEP_CVT]] : index
@@ -151,17 +150,16 @@ subroutine loop_with_variable_step(s,e,st)
   ! CHECK-DAG: %[[I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFloop_with_variable_stepEi"}
   ! CHECK-DAG: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_REF]]
   ! CHECK: %[[S:.*]] = fir.load %[[S_DECL]]#0 : !fir.ref<i32>
-  ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i32) -> index
   ! CHECK: %[[E:.*]] = fir.load %[[E_DECL]]#0 : !fir.ref<i32>
-  ! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i32) -> index
   ! CHECK: %[[ST:.*]] = fir.load %[[ST_DECL]]#0 : !fir.ref<i32>
-  ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index
-  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S]] to %[[E]] step %[[ST]] : i32 {
   do i=s,e,st
-  ! CHECK:  %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
-  ! CHECK:  fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i32>
+  ! CHECK:  fir.store %[[LI]] to %[[I_DECL]]#0 : !fir.ref<i32>
   ! CHECK: }
   end do
+  ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i32) -> index
+  ! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i32) -> index
+  ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index
   ! CHECK: %[[C0:.*]] = arith.constant 0 : index
   ! CHECK: %[[DIFF:.*]] = arith.subi %[[E_CVT]], %[[S_CVT]] : index
   ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[ST_CVT]] : index
@@ -204,21 +202,20 @@ subroutine loop_with_pointer_variables(s,e,st)
 ! CHECK:  %[[S_BOX:.*]] = fir.load %[[S_PTR_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
 ! CHECK:  %[[S_PTR:.*]] = fir.box_addr %[[S_BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
 ! CHECK:  %[[S:.*]] = fir.load %[[S_PTR]] : !fir.ptr<i32>
-! CHECK:  %[[S_CVT:.*]] = fir.convert %[[S]] : (i32) -> index
 ! CHECK:  %[[E_BOX:.*]] = fir.load %[[E_PTR_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
 ! CHECK:  %[[E_PTR:.*]] = fir.box_addr %[[E_BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
 ! CHECK:  %[[E:.*]] = fir.load %[[E_PTR]] : !fir.ptr<i32>
-! CHECK:  %[[E_CVT:.*]] = fir.convert %[[E]] : (i32) -> index
 ! CHECK:  %[[ST_BOX:.*]] = fir.load %[[ST_PTR_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
 ! CHECK:  %[[ST_PTR:.*]] = fir.box_addr %[[ST_BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
 ! CHECK:  %[[ST:.*]] = fir.load %[[ST_PTR]] : !fir.ptr<i32>
-! CHECK:  %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index
-! CHECK:  fir.do_loop %[[LI:[^ ]*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] {
+! CHECK:  fir.do_loop %[[LI:[^ ]*]] = %[[S]] to %[[E]] step %[[ST]] : i32 {
   do iptr=sptr,eptr,stptr
-! CHECK:    %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i32
-! CHECK:    fir.store %[[I_IV]] to %[[I_PTR]] : !fir.ptr<i32>
+! CHECK:    fir.store %[[LI]] to %[[I_PTR]] : !fir.ptr<i32>
 ! CHECK:  }
   end do
+! CHECK:  %[[S_CVT:.*]] = fir.convert %[[S]] : (i32) -> index
+! CHECK:  %[[E_CVT:.*]] = fir.convert %[[E]] : (i32) -> index
+! CHECK:  %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i32) -> index
 ! CHECK:  %[[C0:.*]] = arith.constant 0 : index
 ! CHECK:  %[[DIFF:.*]] = arith.subi %[[E_CVT]], %[[S_CVT]] : index
 ! CHECK:  %[[ADD:.*]] = arith.addi %[[DIFF]], %[[ST_CVT]] : index
@@ -242,19 +239,18 @@ subroutine loop_with_non_default_integer(s,e,st)
   ! CHECK-DAG: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_REF]]
   integer(kind=8):: i
   ! CHECK: %[[S:.*]] = fir.load %[[S_DECL]]#0 : !fir.ref<i64>
-  ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i64) -> index
   ! CHECK: %[[E:.*]] = fir.load %[[E_DECL]]#0 : !fir.ref<i64>
-  ! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i64) -> index
   ! CHECK: %[[ST:.*]] = fir.load %[[ST_DECL]]#0 : !fir.ref<i64>
-  ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i64) -> index
   integer(kind=8) :: s, e, st
 
-  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S_CVT]] to %[[E_CVT]] step %[[ST_CVT]] {
+  ! CHECK: fir.do_loop %[[LI:[^ ]*]] = %[[S]] to %[[E]] step %[[ST]] : i64 {
   do i=s,e,st
-    ! CHECK: %[[I_IV:.*]] = fir.convert %[[LI]] : (index) -> i64
-    ! CHECK: fir.store %[[I_IV]] to %[[I_DECL]]#0 : !fir.ref<i64>
+    ! CHECK: fir.store %[[LI]] to %[[I_DECL]]#0 : !fir.ref<i64>
   ! CHECK: }
   end do
+  ! CHECK: %[[S_CVT:.*]] = fir.convert %[[S]] : (i64) -> index
+  ! CHECK: %[[E_CVT:.*]] = fir.convert %[[E]] : (i64) -> index
+  ! CHECK: %[[ST_CVT:.*]] = fir.convert %[[ST]] : (i64) -> index
   ! CHECK: %[[C0:.*]] = arith.constant 0 : index
   ! CHECK: %[[DIFF:.*]] = arith.subi %[[E_CVT]], %[[S_CVT]] : index
   ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[ST_CVT]] : index
diff --git a/flang/test/Lower/do_loop_unstructured.f90 b/flang/test/Lower/do_loop_unstructured.f90
index 9a7b76eb090a9..5713c1c902836 100644
--- a/flang/test/Lower/do_loop_unstructured.f90
+++ b/flang/test/Lower/do_loop_unstructured.f90
@@ -169,18 +169,20 @@ subroutine nested_structured_in_unstructured()
 ! CHECK:   %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
 ! CHECK:   cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
 ! CHECK: ^[[BODY]]:
-! CHECK:   fir.do_loop %[[J_INDEX:[^ ]*]] =
-! CHECK-SAME: %[[J_LBIDX:[^ ]*]] to %[[J_UBIDX:[^ ]*]] step %[[ST:[^ ]*]] {
-! CHECK:     %[[J_IV:.*]] = fir.convert %[[J_INDEX]] : (index) -> i32
+! CHECK:   fir.do_loop %[[J_IV:[^ ]*]] =
+! CHECK-SAME: %[[J_LB:[^ ]*]] to %[[J_UB:[^ ]*]] step %[[J_ST:[^ ]*]] : i32 {
 ! CHECK:     fir.store %[[J_IV]] to %[[LOOP_VAR_J_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   }
+! CHECK:   %[[J_LBIDX:.*]] = fir.convert %[[J_LB]] : (i32) -> index
+! CHECK:   %[[J_UBIDX:.*]] = fir.convert %[[J_UB]] : (i32) -> index
+! CHECK:   %[[J_STIDX:.*]] = fir.convert %[[J_ST]] : (i32) -> index
 ! CHECK:   %[[J_C0:.*]] = arith.constant 0 : index
 ! CHECK:   %[[J_DIFF:.*]] = arith.subi %[[J_UBIDX]], %[[J_LBIDX]] : index
-! CHECK:   %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[ST]] : index
-! CHECK:   %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[ST]] : index
+! CHECK:   %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[J_STIDX]] : index
+! CHECK:   %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[J_STIDX]] : index
 ! CHECK:   %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[J_C0]] : index
 ! CHECK:   %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[J_C0]], %[[J_TRIP]] : index
-! CHECK:   %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[ST]] : index
+! CHECK:   %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[J_STIDX]] : index
 ! CHECK:   %[[J_LASTIDX:.*]] = arith.addi %[[J_LBIDX]], %[[J_MUL]] : index
 ! CHECK:   %[[J_LAST:.*]] = fir.convert %[[J_LASTIDX]] : (index) -> i32
 ! CHECK:   fir.store %[[J_LAST]] to %[[LOOP_VAR_J_DECL]]#0 : !fir.ref<i32>
diff --git a/flang/test/Lower/infinite_loop.f90 b/flang/test/Lower/infinite_loop.f90
index d58473ccbf049..e9cf0dfb16a59 100644
--- a/flang/test/Lower/infinite_loop.f90
+++ b/flang/test/Lower/infinite_loop.f90
@@ -82,7 +82,7 @@ subroutine structured_loop_in_infinite(i)
 ! CHECK-DAG:  %[[C100:.*]] = arith.constant 100 : i32
 ! CHECK-DAG:  %[[C1:.*]] = arith.constant 1 : i32
 ! CHECK-DAG:  %[[C10:.*]] = arith.constant 10 : i32
-! CHECK-DAG:  %[[C1_1:.*]] = arith.constant 1 : index
+! CHECK-DAG:  %[[C0:.*]] = arith.constant 0 : index
 ! CHECK-DAG:  %[[I_DECL:.*]] = fir.declare %[[I_REF]] {{.*}}
 ! CHECK-DAG:  %[[J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFstructured_loop_in_infiniteEj"}
 ! CHECK-DAG:  %[[J_DECL:.*]] = fir.declare %[[J_REF]] {{.*}}
@@ -94,18 +94,20 @@ subroutine structured_loop_in_infinite(i)
 ! CHECK: ^[[EXIT]]:
 ! CHECK:  cf.br ^[[RETURN:.*]]
 ! CHECK: ^[[BODY2:.*]]:
-! CHECK:  %[[C1_INDEX:.*]] = fir.convert %[[C1]] : (i32) -> index
-! CHECK:  %[[C10_INDEX:.*]] = fir.convert %[[C10]] : (i32) -> index
 ! CHECK:  fir.do_loop %[[J:[^ ]*]] =
-! CHECK-SAME: %[[C1_INDEX]] to %[[C10_INDEX]] step %[[C1_1]] {
-! CHECK:    %[[J_IV:.*]] = fir.convert %[[J]] : (index) -> i32
-! CHECK:    fir.store %[[J_IV]] to %[[J_DECL]] : !fir.ref<i32>
+! CHECK-SAME: %[[C1]] to %[[C10]] step %[[C1]] : i32 {
+! CHECK:    fir.store %[[J]] to %[[J_DECL]] : !fir.ref<i32>
 ! CHECK:  }
+! CHECK:  %[[C1_INDEX:.*]] = fir.convert %[[C1]] : (i32) -> index
+! CHECK:  %[[C10_INDEX:.*]] = fir.convert %[[C10]] : (i32) -> index
+! CHECK:  %[[C1_STEP_INDEX:.*]] = fir.convert %[[C1]] : (i32) -> index
 ! CHECK:  %[[J_DIFF:.*]] = arith.subi %[[C10_INDEX]], %[[C1_INDEX]] : index
-! CHECK:  %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[C1_1]] : index
-! CHECK:  %[[J_CMP:.*]] = arith.cmpi slt, %[[J_ADD]], %{{.*}} : index
-! CHECK:  %[[J_SEL:.*]] = arith.select %[[J_CMP]], %{{.*}}, %[[J_ADD]] : index
-! CHECK:  %[[J_LASTIDX:.*]] = arith.addi %[[C1_INDEX]], %[[J_SEL]] : index
+! CHECK:  %[[J_ADD:.*]] = arith.addi %[[J_DIFF]], %[[C1_STEP_INDEX]] : index
+! CHECK:  %[[J_TRIP:.*]] = arith.divsi %[[J_ADD]], %[[C1_STEP_INDEX]] : index
+! CHECK:  %[[J_CMP:.*]] = arith.cmpi slt, %[[J_TRIP]], %[[C0]] : index
+! CHECK:  %[[J_SEL:.*]] = arith.select %[[J_CMP]], %[[C0]], %[[J_TRIP]] : index
+! CHECK:  %[[J_MUL:.*]] = arith.muli %[[J_SEL]], %[[C1_STEP_INDEX]] : index
+! CHECK:  %[[J_LASTIDX:.*]] = arith.addi %[[C1_INDEX]], %[[J_MUL]] : index
 ! CHECK:  %[[J_LAST:.*]] = fir.convert %[[J_LASTIDX]] : (index) -> i32
 ! CHECK:  fir.store %[[J_LAST]] to %[[J_DECL]] : !fir.ref<i32>
 ! CHECK:  cf.br ^[[BODY1]]
diff --git a/flang/test/Lower/loops2.f90 b/flang/test/Lower/loops2.f90
index 78517aa013d6c..e38900dc57ff6 100644
--- a/flang/test/Lower/loops2.f90
+++ b/flang/test/Lower/loops2.f90
@@ -15,17 +15,20 @@ subroutine test_pointer()
 ! CHECK: %[[PTR:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMtest_loop_varEi_pointer"}
 ! CHECK: %[[BOX:.*]] = fir.load %[[PTR]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
 ! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
-! CHECK: fir.do_loop %{{.*}} = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
-! CHECK:   fir.store %{{.*}} to %[[ADDR]] : !fir.ptr<i32>
+! CHECK: fir.do_loop %[[IV:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] : i32 {
+! CHECK:   fir.store %[[IV]] to %[[ADDR]] : !fir.ptr<i32>
 ! CHECK: }
+! CHECK: %[[LBIDX:.*]] = fir.convert %[[LB]] : (i32) -> index
+! CHECK: %[[UBIDX:.*]] = fir.convert %[[UB]] : (i32) -> index
+! CHECK: %[[STEPIDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
 ! CHECK: %[[C0:.*]] = arith.constant 0 : index
-! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
-! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
-! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : index
+! CHECK: %[[DIFF:.*]] = arith.subi %[[UBIDX]], %[[LBIDX]] : index
+! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEPIDX]] : index
+! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEPIDX]] : index
 ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
 ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
-! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEPIDX]] : index
+! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LBIDX]], %[[MUL]] : index
 ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
 ! CHECK: fir.store %[[LAST]] to %[[ADDR]] : !fir.ptr<i32>
   end subroutine
@@ -37,17 +40,20 @@ subroutine test_allocatable()
 ! CHECK: %[[ALLOC:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMtest_loop_varEi_allocatable"}
 ! CHECK: %[[BOX:.*]] = fir.load %[[ALLOC]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
 ! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
-! CHECK: fir.do_loop %{{.*}} = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
-! CHECK:   fir.store %{{.*}} to %[[ADDR]] : !fir.heap<i32>
+! CHECK: fir.do_loop %[[IV:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] : i32 {
+! CHECK:   fir.store %[[IV]] to %[[ADDR]] : !fir.heap<i32>
 ! CHECK: }
+! CHECK: %[[LBIDX:.*]] = fir.convert %[[LB]] : (i32) -> index
+! CHECK: %[[UBIDX:.*]] = fir.convert %[[UB]] : (i32) -> index
+! CHECK: %[[STEPIDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
 ! CHECK: %[[C0:.*]] = arith.constant 0 : index
-! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
-! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
-! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : index
+! CHECK: %[[DIFF:.*]] = arith.subi %[[UBIDX]], %[[LBIDX]] : index
+! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEPIDX]] : index
+! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEPIDX]] : index
 ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
 ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
-! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEPIDX]] : index
+! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LBIDX]], %[[MUL]] : index
 ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
 ! CHECK: fir.store %[[LAST]] to %[[ADDR]] : !fir.heap<i32>
   end subroutine
diff --git a/flang/test/Lower/mixed_loops.f90 b/flang/test/Lower/mixed_loops.f90
index f62a40c5d4b83..7059f58eaef1f 100644
--- a/flang/test/Lower/mixed_loops.f90
+++ b/flang/test/Lower/mixed_loops.f90
@@ -76,10 +76,9 @@ subroutine do_inside_while_loop
 
       ! 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 %[[LI:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] {
-        ! CHECK: %[[IV:.*]] = fir.convert %[[LI]] : (index) -> i32
-        ! CHECK: fir.store %[[IV]] to %[[I]]#0 : !fir.ref<i32>
+      ! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
+      ! CHECK: fir.do_loop %[[LI:.*]] = %[[LB:.*]] to %[[UB:.*]] step %[[STEP:.*]] : i32 {
+        ! CHECK: fir.store %[[LI]] to %[[I]]#0 : !fir.ref<i32>
         ! CHECK: %[[C2:.*]] = arith.constant 2 : i32
         ! CHECK: %[[J2VAL:.*]] = fir.load %[[J]]#0 : !fir.ref<i32>
         ! CHECK: %[[JINC:.*]] = arith.muli %[[C2]], %[[J2VAL]] : i32
@@ -87,14 +86,17 @@ subroutine do_inside_while_loop
       do i=8,13
         j=j*2
 
+      ! CHECK: %[[LBIDX:.*]] = fir.convert %[[LB]] : (i32) -> index
+      ! CHECK: %[[UBIDX:.*]] = fir.convert %[[UB]] : (i32) -> index
+      ! CHECK: %[[STEPIDX:.*]] = fir.convert %[[STEP]] : (i32) -> index
       ! CHECK: %[[C0:.*]] = arith.constant 0 : index
-      ! CHECK: %[[DIFF:.*]] = arith.subi %[[UB]], %[[LB]] : index
-      ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEP]] : index
-      ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEP]] : index
+      ! CHECK: %[[DIFF:.*]] = arith.subi %[[UBIDX]], %[[LBIDX]] : index
+      ! CHECK: %[[ADD:.*]] = arith.addi %[[DIFF]], %[[STEPIDX]] : index
+      ! CHECK: %[[TRIP:.*]] = arith.divsi %[[ADD]], %[[STEPIDX]] : index
       ! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[TRIP]], %[[C0]] : index
       ! CHECK: %[[SEL:.*]] = arith.select %[[CMP]], %[[C0]], %[[TRIP]] : index
-      ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEP]] : index
-      ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LB]], %[[MUL]] : index
+      ! CHECK: %[[MUL:.*]] = arith.muli %[[SEL]], %[[STEPIDX]] : index
+      ! CHECK: %[[LASTIDX:.*]] = arith.addi %[[LBIDX]], %[[MUL]] : index
       ! CHECK: %[[LAST:.*]] = fir.convert %[[LASTIDX]] : (index) -> i32
       ! CHECK: fir.store %[[LAST]] to %[[I]]#0 : !fir.ref<i32>
       end do
diff --git a/flang/test/Lower/nsw.f90 b/flang/test/Lower/nsw.f90
index 5f216b830649c..fa18dbff97ecc 100644
--- a/flang/test/Lower/nsw.f90
+++ b/flang/test/Lower/nsw.f90
@@ -77,13 +77,15 @@ subroutine loop_params(a,lb,ub,st)
 ! CHECK:           %[[VAL_14:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32>
 ! CHECK:           %[[VAL_16:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32>
 ! CHECK:           %[[VAL_25:.*]] = arith.addi %[[VAL_14]], %[[VAL_5]] overflow<nsw> : i32
-! CHECK:           %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i32) -> index
-! CHECK:           %[[VAL_27:.*]] = arith.subi %[[VAL_16]], %[[VAL_5]] overflow<nsw> : i32
-! CHECK:           %[[VAL_28:.*]] = fir.convert %[[VAL_27]] : (i32) -> index
-! CHECK:           %[[VAL_29:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
-! CHECK:           %[[VAL_30:.*]] = arith.muli %[[VAL_29]], %[[VAL_4]] overflow<nsw> : i32
-! CHECK:           %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (i32) -> index
-! CHECK:           fir.do_loop %[[VAL_34:.*]] = %[[VAL_26]] to %[[VAL_28]] step %[[VAL_31]] {
+! CHECK:           %[[VAL_26:.*]] = arith.subi %[[VAL_16]], %[[VAL_5]] overflow<nsw> : i32
+! CHECK:           %[[VAL_27:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
+! CHECK:           %[[VAL_28:.*]] = arith.muli %[[VAL_27]], %[[VAL_4]] overflow<nsw> : i32
+! CHECK:           fir.do_loop %[[VAL_29:.*]] = %[[VAL_25]] to %[[VAL_26]] step %[[VAL_28]] : i32 {
+! CHECK:             fir.store %[[VAL_29]] to %[[VAL_12]] : !fir.ref<i32>
+! CHECK:           }
+! CHECK:           %[[VAL_30:.*]] = fir.convert %[[VAL_25]] : (i32) -> index
+! CHECK:           %[[VAL_31:.*]] = fir.convert %[[VAL_26]] : (i32) -> index
+! CHECK:           %[[VAL_32:.*]] = fir.convert %[[VAL_28]] : (i32) -> index
 
 subroutine loop_params2(a,lb,ub,st)
   integer :: i, lb, ub, st
diff --git a/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90 b/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90
index 790bda5bb7d23..f147a2bfb664d 100644
--- a/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90
+++ b/flang/test/Transforms/DoConcurrent/skip_all_nested_loops.f90
@@ -48,10 +48,9 @@ program main
 
 ! COMMON: omp.wsloop {
 ! COMMON: omp.loop_nest ({{[^[:space:]]+}}) {{.*}} {
-! COMMON:   fir.do_loop %[[J_IV:.*]] = {{.*}} to {{.*}} step {{.*}} {
-! COMMON:     %[[J_IV_CONV:.*]] = fir.convert %[[J_IV]] : (index) -> i32
-! HOST:       fir.store %[[J_IV_CONV]] to %[[ORIG_J_DECL]]#0
-! DEVICE:     fir.store %[[J_IV_CONV]] to %[[TARGET_J_DECL]]#0
+! COMMON:   fir.do_loop %[[J_IV:.*]] = {{.*}} to {{.*}} step {{.*}} : i32 {
+! HOST:       fir.store %[[J_IV]] to %[[ORIG_J_DECL]]#0
+! DEVICE:     fir.store %[[J_IV]] to %[[TARGET_J_DECL]]#0
 
 ! COMMON:     fir.do_concurrent {
 ! COMMON:         %[[ORIG_K_ALLOC:.*]] = fir.alloca i32 {bindc_name = "k"}

>From 4a6219b402eee44feadb02002af3f58c97e82dc0 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 20 Jul 2026 03:46:35 -0700
Subject: [PATCH 12/12] [flang][test] Update unstructured loop checks for typed
 IVs

Remove stale iter_arg and fir.result expectations after plain DO loops switched to typed induction variables.
---
 flang/test/Lower/OpenMP/unstructured.f90         | 3 ---
 flang/test/Lower/do_loop_execute_region_wrap.f90 | 4 ----
 flang/test/Lower/do_loop_unstructured.f90        | 6 ++----
 flang/test/Lower/mixed_loops.f90                 | 3 +--
 4 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/flang/test/Lower/OpenMP/unstructured.f90 b/flang/test/Lower/OpenMP/unstructured.f90
index b60c1f5b7ef82..5d680576d26c6 100644
--- a/flang/test/Lower/OpenMP/unstructured.f90
+++ b/flang/test/Lower/OpenMP/unstructured.f90
@@ -101,7 +101,6 @@ subroutine ss2(n) ! unstructured OpenMP construct; loop exit inside construct
 ! CHECK:           omp.yield
 ! CHECK:         }
 ! CHECK:       }
-! CHECK:       fir.result
 ! CHECK:     }
 ! CHECK:     omp.terminator
 ! CHECK:   }
@@ -217,7 +216,6 @@ subroutine ss5() ! EXIT inside OpenMP wsloop (inside parallel)
 ! CHECK:          omp.yield
 ! CHECK:        }
 ! CHECK:      }
-! CHECK:      fir.result
 ! CHECK:    }
 ! CHECK:    omp.terminator
 ! CHECK:  }
@@ -263,7 +261,6 @@ subroutine ss6() ! EXIT inside OpenMP wsloop in a do loop (inside parallel)
 ! CHECK:       }
 ! CHECK:       omp.terminator
 ! CHECK:     }
-! CHECK:     fir.result
 ! CHECK:   }
 ! CHECK:   return
 subroutine ss7() ! EXIT inside OpenMP parallel do (inside do loop)
diff --git a/flang/test/Lower/do_loop_execute_region_wrap.f90 b/flang/test/Lower/do_loop_execute_region_wrap.f90
index 92bb4e41e9b3f..0725f50c17343 100644
--- a/flang/test/Lower/do_loop_execute_region_wrap.f90
+++ b/flang/test/Lower/do_loop_execute_region_wrap.f90
@@ -20,7 +20,6 @@ subroutine wrapped_unstructured(n, a)
 ! CHECK:             fir.unreachable
 ! CHECK:             scf.yield
 ! CHECK:           }
-! CHECK:           fir.result
 
 ! Unstructured DO with a GOTO targeting a label outside the construct that
 ! is reachable on a path distinct from the loop's natural exit: not wrapped.
@@ -141,8 +140,6 @@ subroutine outer_structured_inner_wrapped(n, a)
 ! CHECK:               fir.unreachable
 ! CHECK:               scf.yield
 ! CHECK:             }
-! CHECK:             fir.result
-! CHECK:           fir.result
 
 ! Structured outer DO containing an unstructured inner DO (the inner DO has
 ! an EXIT that targets its own construct exit). isUnstructured does not
@@ -168,4 +165,3 @@ subroutine outer_fir_do_loop_inner_unstructured_do(n, a)
 ! CHECK:             cf.cond_br
 ! CHECK:             scf.yield
 ! CHECK:           }
-! CHECK:           fir.result
diff --git a/flang/test/Lower/do_loop_unstructured.f90 b/flang/test/Lower/do_loop_unstructured.f90
index 5713c1c902836..3d22a3e277812 100644
--- a/flang/test/Lower/do_loop_unstructured.f90
+++ b/flang/test/Lower/do_loop_unstructured.f90
@@ -112,8 +112,8 @@ subroutine nested_unstructured()
 ! CHECK:   %[[LOOP_VAR_J_DECL:.*]]:2 = hlfir.declare %[[LOOP_VAR_J_REF]]
 ! CHECK:   %[[LOOP_VAR_K_REF:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFnested_unstructuredEk"}
 ! CHECK:   %[[LOOP_VAR_K_DECL:.*]]:2 = hlfir.declare %[[LOOP_VAR_K_REF]]
-! CHECK:   fir.do_loop %{{[^ ]+}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{[^ ]+}} = %{{.*}}) -> (i32) {
-! CHECK:     fir.do_loop %{{[^ ]+}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{[^ ]+}} = %{{.*}}) -> (i32) {
+! CHECK:   fir.do_loop %{{[^ ]+}} = %{{.*}} to %{{.*}} step %{{.*}} : i32 {
+! CHECK:     fir.do_loop %{{[^ ]+}} = %{{.*}} to %{{.*}} step %{{.*}} : i32 {
 ! CHECK:       scf.execute_region no_inline {
 ! CHECK:         cf.br ^[[HEADER_K:.*]]
 ! CHECK:       ^[[HEADER_K]]:
@@ -131,9 +131,7 @@ subroutine nested_unstructured()
 ! CHECK:       ^[[EXIT_K]]:
 ! CHECK:         scf.yield
 ! CHECK:       }
-! CHECK:       fir.result %{{.*}} : i32
 ! CHECK:     }
-! CHECK:     fir.result %{{.*}} : i32
 ! CHECK:   }
 ! CHECK:   return
 
diff --git a/flang/test/Lower/mixed_loops.f90 b/flang/test/Lower/mixed_loops.f90
index 7059f58eaef1f..9c774caccf131 100644
--- a/flang/test/Lower/mixed_loops.f90
+++ b/flang/test/Lower/mixed_loops.f90
@@ -12,7 +12,7 @@ subroutine while_inside_do_loop
   ! CHECK-DAG: %[[J:.*]]:2 = hlfir.declare %[[J_ADDR]]
   integer :: i, j
 
-  ! CHECK: fir.do_loop %{{[^ ]+}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[I_IV:.*]] = %{{.*}}) -> (i32) {
+  ! CHECK: fir.do_loop %[[I_IV:.*]] = %{{.*}} to %{{.*}} step %{{.*}} : i32 {
   ! CHECK:   fir.store %[[I_IV]] to %[[I]]#0 : !fir.ref<i32>
   do i=8,13
     ! CHECK:   %[[C3:.*]] = arith.constant 3 : i32
@@ -38,7 +38,6 @@ subroutine while_inside_do_loop
     ! CHECK:   ^[[EXIT2]]:
     ! CHECK:     scf.yield
     ! CHECK:   }
-    ! CHECK:   fir.result %{{.*}} : i32
   end do
   ! CHECK: }
 



More information about the flang-commits mailing list