[llvm-branch-commits] [flang] [mlir] [mlir][flang][OpenMP] Select depend and affinity iterators per locator (PR #227454)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Oct 6 12:57:42 PDT 2026


https://github.com/chichunchen updated https://github.com/llvm/llvm-project/pull/227454

>From 499cc2a06e8c634643de4b9970d5904bd8fbc250 Mon Sep 17 00:00:00 2001
From: "Chi-Chun, Chen" <chichun.chen at hpe.com>
Date: Wed, 30 Sep 2026 12:18:55 -0500
Subject: [PATCH 1/3] [mlir][flang][OpenMP] Select depend and affinity
 iterators per locator

Flang expands each iterator-dependent depend or affinity locator over all
ranges in the clause, including iterators absent from that locator. For
example:

  depend(iterator(i=1:2, j=3:m), in: a(i))

When m < 3, the unused empty j range suppresses both required dependences
on a. This can lose task ordering. A nonempty unused range instead repeats
entries unnecessarily; affinity locators have the same expansion problem.

Select ranges according to the iterator identifiers appearing in each
locator's source, preserving declaration order. Making this change safely
also requires preserving source occurrences and handling empty ranges:

- Record resolved iterator references before using the folded expression
  for lowering. In a(j/d + 0*i), folding removes 0*i, but an empty i range
  must still suppress the locator and prevent evaluation of j/d.
- Keep references per locator and separate from object identity, since
  distinct source locators can have equal folded designators.
- Rely on the zero-trip counting from #229198: removing an unused range
  can expose an empty range previously masked by multiplication by zero.
- Accept constant empty ranges in the verifier, retaining the zero-step
  diagnostic so constant and dynamic empty ranges behave consistently.
- Test depend and affinity counts, locator evaluation guards, folded
  references, shadowed names, and target-clause propagation.

Addresses the prerequisite fix requested for #197757:
https://github.com/llvm/llvm-project/pull/197757#discussion_r4079319531

Fixes https://github.com/llvm/llvm-project/issues/227443.

Assisted with codex.
---
 flang/include/flang/Lower/OpenMP/Clauses.h    |  12 +
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |  44 ++-
 flang/lib/Lower/OpenMP/Clauses.cpp            |  50 +++-
 flang/lib/Lower/OpenMP/Utils.cpp              |  29 +-
 flang/lib/Lower/OpenMP/Utils.h                |   9 +-
 flang/test/Lower/OpenMP/depend-iterator.f90   |  92 ++++++
 .../Lower/OpenMP/iterator-empty-range.f90     | 282 ++++++++++++++++++
 .../OpenMP/iterator-source-occurrences.f90    | 149 +++++++++
 flang/test/Lower/OpenMP/task-affinity.f90     | 106 +++++++
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  21 +-
 mlir/test/Dialect/OpenMP/invalid.mlir         |  28 --
 mlir/test/Dialect/OpenMP/iterator-empty.mlir  |  18 ++
 .../Target/LLVMIR/openmp-iterator-empty.mlir  |  54 ++++
 13 files changed, 799 insertions(+), 95 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/iterator-empty-range.f90
 create mode 100644 flang/test/Lower/OpenMP/iterator-source-occurrences.f90
 create mode 100644 mlir/test/Dialect/OpenMP/iterator-empty.mlir
 create mode 100644 mlir/test/Target/LLVMIR/openmp-iterator-empty.mlir

diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h b/flang/include/flang/Lower/OpenMP/Clauses.h
index 9d4b1aa20bbe99..fb5b5d50670f72 100644
--- a/flang/include/flang/Lower/OpenMP/Clauses.h
+++ b/flang/include/flang/Lower/OpenMP/Clauses.h
@@ -76,6 +76,11 @@ struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
   using IdTy = Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>;
   using ExprTy = Fortran::lower::omp::ExprTy;
 
+  ObjectT() = default;
+  ObjectT(IdTy id) : identity(std::move(id)) {}
+  ObjectT(Fortran::semantics::Symbol *symbol, std::optional<ExprTy> designator)
+      : identity{symbol, std::move(designator)} {}
+
   IdTy id() const { return identity; }
   Fortran::semantics::Symbol *sym() const { return identity.symbol; }
   const std::optional<ExprTy> &ref() const { return identity.designator; }
@@ -85,6 +90,13 @@ struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
   }
 
   IdTy identity;
+
+  // Resolved iterator references in the source locator, before expression
+  // folding can remove them. This is per-occurrence metadata, not object
+  // identity: a(j) and a(j + 0*i) may have equal folded designators.
+  // An engaged, empty list means the locator references no clause iterators.
+  std::optional<Fortran::lower::omp::List<const Fortran::semantics::Symbol *>>
+      sourceIteratorReferences = std::nullopt;
 };
 } // namespace tomp::type
 
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index e41223b5b16c01..6d235c4279171d 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -338,25 +338,23 @@ static mlir::Value buildIteratorOp(Fortran::lower::AbstractConverter &converter,
 }
 
 template <typename ClauseTuple>
-static void collectIteratorIVs(
-    const ClauseTuple &clause, Fortran::lower::AbstractConverter &converter,
-    Fortran::lower::StatementContext &stmtCtx,
-    llvm::SmallVectorImpl<IteratorRange> &iteratorRanges,
-    llvm::SmallPtrSetImpl<const Fortran::semantics::Symbol *> &ivSyms) {
+static llvm::SmallVector<IteratorRange>
+lowerIteratorRanges(const ClauseTuple &clause,
+                    Fortran::lower::AbstractConverter &converter,
+                    Fortran::lower::StatementContext &stmtCtx) {
   auto &iteratorModifier =
       std::get<std::optional<omp::clause::Iterator>>(clause.t);
   if (!iteratorModifier.has_value())
-    return;
+    return {};
 
+  llvm::SmallVector<IteratorRange> iteratorRanges;
   mlir::Location clauseLocation = converter.getCurrentLocation();
   const auto &iteratorModifierSpecs = *iteratorModifier;
   iteratorRanges.reserve(iteratorModifierSpecs.size());
   for (const auto &itSpec : iteratorModifierSpecs)
     iteratorRanges.push_back(lowerIteratorRange<Fortran::evaluate::SomeType>(
         converter, itSpec, stmtCtx, clauseLocation));
-
-  for (const IteratorRange &r : iteratorRanges)
-    ivSyms.insert(&r.ivSym->GetUltimate());
+  return iteratorRanges;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1046,22 +1044,18 @@ bool ClauseProcessor::processAffinity(
               .getResult();
         };
 
-        llvm::SmallVector<IteratorRange> iteratorRanges;
-        llvm::SmallPtrSet<const Fortran::semantics::Symbol *, 4> ivSyms;
-
-        auto &iteratorModifier =
-            std::get<std::optional<omp::clause::Iterator>>(clause.t);
-        collectIteratorIVs(clause, converter, stmtCtx, iteratorRanges, ivSyms);
+        auto iteratorRanges = lowerIteratorRanges(clause, converter, stmtCtx);
 
         TodoLocators(clauseLocation, objects);
 
         for (const omp::Object &object : objects) {
           llvm::SmallVector<mlir::Value> bounds;
           std::stringstream asFortran;
-          if (iteratorModifier.has_value() &&
-              hasIteratorIVReference(object, ivSyms)) {
+          llvm::SmallVector<IteratorRange> objectRanges =
+              getIteratorRangesForObject(object, iteratorRanges);
+          if (!objectRanges.empty()) {
             mlir::Value iterHandle = buildIteratorOp(
-                converter, clauseLocation, iterTy, iteratorRanges,
+                converter, clauseLocation, iterTy, objectRanges,
                 [&](fir::FirOpBuilder &builder, mlir::Location loc,
                     llvm::ArrayRef<mlir::Value> /*ivs*/) -> mlir::Value {
                   lower::StatementContext iterStmtCtx;
@@ -1509,12 +1503,7 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
       return dependVar;
     };
 
-    auto &iteratorModifier =
-        std::get<std::optional<omp::clause::Iterator>>(clause.t);
-
-    llvm::SmallVector<IteratorRange> iteratorRanges;
-    llvm::SmallPtrSet<const Fortran::semantics::Symbol *, 4> ivSyms;
-    collectIteratorIVs(clause, converter, stmtCtx, iteratorRanges, ivSyms);
+    auto iteratorRanges = lowerIteratorRanges(clause, converter, stmtCtx);
 
     mlir::Type ptrTy =
         mlir::LLVM::LLVMPointerType::get(&converter.getMLIRContext());
@@ -1522,10 +1511,11 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
         mlir::omp::IteratedType::get(&converter.getMLIRContext(), ptrTy);
 
     for (const omp::Object &object : objects) {
-      if (iteratorModifier.has_value() &&
-          hasIteratorIVReference(object, ivSyms)) {
+      llvm::SmallVector<IteratorRange> objectRanges =
+          getIteratorRangesForObject(object, iteratorRanges);
+      if (!objectRanges.empty()) {
         mlir::Value iterHandle = buildIteratorOp(
-            converter, clauseLocation, iterTy, iteratorRanges,
+            converter, clauseLocation, iterTy, objectRanges,
             [&](fir::FirOpBuilder &builder, mlir::Location loc,
                 llvm::ArrayRef<mlir::Value> /*ivs*/) -> mlir::Value {
               lower::StatementContext iterStmtCtx;
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index ee16ae55af30f3..5ef2af3962ad54 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -11,6 +11,7 @@
 #include "flang/Common/idioms.h"
 #include "flang/Evaluate/expression.h"
 #include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Parser/parse-tree-visitor.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/expression.h"
 #include "flang/Semantics/openmp-modifiers.h"
@@ -362,6 +363,49 @@ Iterator makeIterator(const parser::OmpIterator &inp,
   return iterator;
 }
 
+// Walk source syntax rather than the analyzed designator: folding can remove
+// an iterator reference that still determines whether a locator is evaluated.
+struct IteratorReferenceCollector {
+  template <typename T>
+  bool Pre(const T &) {
+    return true;
+  }
+  template <typename T>
+  void Post(const T &) {}
+
+  bool Pre(const parser::Name &name) {
+    if (name.symbol) {
+      const semantics::Symbol *symbol = &name.symbol->GetUltimate();
+      if (llvm::is_contained(iterators, symbol) &&
+          !llvm::is_contained(references, symbol))
+        references.push_back(symbol);
+    }
+    return true;
+  }
+
+  const List<const semantics::Symbol *> &iterators;
+  List<const semantics::Symbol *> &references;
+};
+
+static ObjectList makeIteratorObjects(const parser::OmpObjectList &objects,
+                                      const std::optional<Iterator> &iterator,
+                                      semantics::SemanticsContext &semaCtx) {
+  if (!iterator)
+    return makeObjects(objects, semaCtx);
+
+  List<const semantics::Symbol *> symbols;
+  for (const auto &specifier : *iterator)
+    symbols.push_back(&std::get<Object>(specifier.t).sym()->GetUltimate());
+
+  return makeList(objects.v, [&](const parser::OmpObject &source) {
+    Object object = makeObject(source, semaCtx);
+    auto &references = object.sourceIteratorReferences.emplace();
+    IteratorReferenceCollector collector{symbols, references};
+    parser::Walk(source, collector);
+    return object;
+  });
+}
+
 DefinedOperator makeDefinedOperator(const parser::DefinedOperator &inp,
                                     semantics::SemanticsContext &semaCtx) {
   CLAUSET_ENUM_CONVERT( //
@@ -488,8 +532,9 @@ Affinity make(const parser::OmpClause::Affinity &inp,
   auto &&maybeIter =
       m0 ? makeIterator(*m0, semaCtx) : std::optional<Iterator>{};
 
+  auto objects = makeIteratorObjects(t1, maybeIter, semaCtx);
   return Affinity{{/*Iterator=*/std::move(maybeIter),
-                   /*LocatorList=*/makeObjects(t1, semaCtx)}};
+                   /*LocatorList=*/std::move(objects)}};
 }
 
 Align make(const parser::OmpClause::Align &inp,
@@ -764,10 +809,11 @@ Depend makeDepend(const parser::OmpDependClause::TaskDep &inp,
 
   auto &&maybeIter =
       m0 ? makeIterator(*m0, semaCtx) : std::optional<Iterator>{};
+  auto objects = makeIteratorObjects(t1, maybeIter, semaCtx);
   return Depend{{/*DependenceType=*/makeDepType(*m1),
                  /*Iterator=*/std::move(maybeIter),
                  /*Vector=*/std::nullopt,
-                 /*LocatorList=*/makeObjects(t1, semaCtx)}};
+                 /*LocatorList=*/std::move(objects)}};
 }
 
 // depend(source) / depend(sink: vec) on ordered (4.5..5.1 spelling, deprecated
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index e05a3eab6fad6d..f53429a615a391 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -1086,21 +1086,20 @@ mlir::Value genAffinityLen(fir::FirOpBuilder &builder, mlir::Location loc,
       builder, loc, getTotalElements(builder, loc, entity), elemBytes);
 }
 
-bool hasIteratorIVReference(
-    const omp::Object &object,
-    const llvm::SmallPtrSetImpl<const Fortran::semantics::Symbol *> &ivSyms) {
-  auto ref = object.ref();
-  if (!ref)
-    return false;
-
-  Fortran::lower::SomeExpr expr = toEvExpr(*ref);
-
-  for (Fortran::evaluate::SymbolRef s : CollectSymbols(expr)) {
-    const Fortran::semantics::Symbol &ult = s->GetUltimate();
-    if (ivSyms.contains(&ult))
-      return true;
-  }
-  return false;
+llvm::SmallVector<IteratorRange>
+getIteratorRangesForObject(const omp::Object &object,
+                           llvm::ArrayRef<IteratorRange> ranges) {
+  llvm::SmallVector<IteratorRange> objectRanges;
+  if (ranges.empty())
+    return objectRanges;
+
+  assert(object.sourceIteratorReferences &&
+         "expected source iterator references for the locator");
+  for (const IteratorRange &range : ranges)
+    if (llvm::is_contained(*object.sourceIteratorReferences,
+                           &range.ivSym->GetUltimate()))
+      objectRanges.push_back(range);
+  return objectRanges;
 }
 
 void defaultMangler(Fortran::lower::AbstractConverter &converter,
diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h
index 4560c9df349b2d..3228905fd57c48 100644
--- a/flang/lib/Lower/OpenMP/Utils.h
+++ b/flang/lib/Lower/OpenMP/Utils.h
@@ -216,9 +216,12 @@ struct IteratorRange {
   Fortran::semantics::Symbol *ivSym = nullptr;
 };
 
-bool hasIteratorIVReference(
-    const omp::Object &object,
-    const llvm::SmallPtrSetImpl<const Fortran::semantics::Symbol *> &ivSyms);
+/// Select ranges referenced in the locator source, even if folding removes
+/// their occurrences from the analyzed expression. Preserve declaration order.
+/// An empty result means the locator is not iterator-dependent.
+llvm::SmallVector<IteratorRange>
+getIteratorRangesForObject(const omp::Object &object,
+                           llvm::ArrayRef<IteratorRange> ranges);
 
 /// Default name mangler for implicit default mappers.
 ///
diff --git a/flang/test/Lower/OpenMP/depend-iterator.f90 b/flang/test/Lower/OpenMP/depend-iterator.f90
index d785c629f5e6e2..47431fce1b1a77 100644
--- a/flang/test/Lower/OpenMP/depend-iterator.f90
+++ b/flang/test/Lower/OpenMP/depend-iterator.f90
@@ -10,6 +10,98 @@
 ! task
 !===============================================================================
 
+! The unused j range must not suppress a(i) when m < 3.
+subroutine depend_unused_iterator(m)
+  integer :: m
+  integer :: a(4)
+
+  !$omp task depend(iterator(i = 1:2, j = 3:m), in: a(i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPdepend_unused_iterator(
+! CHECK: %[[A:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFdepend_unused_iteratorEa")
+! CHECK: %[[M:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFdepend_unused_iteratorEm")
+! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
+! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
+! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
+! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
+! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
+! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
+! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
+! CHECK-SAME: (!fir.ref<i32>) -> !llvm.ptr
+! CHECK: omp.yield(%[[PTR_I]] : !llvm.ptr)
+! CHECK: } -> !omp.iterated<!llvm.ptr>
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task depend(
+! CHECK-SAME: taskdependin -> %[[IT_I]] : !omp.iterated<!llvm.ptr>) {
+
+! Each locator uses its own iterator subset; c remains non-iterated.
+subroutine depend_per_locator(m)
+  integer :: m
+  integer :: a(4), b(4), c
+
+  !$omp task depend(iterator(i = 1:2, j = 3:m), in: a(i), b(j), c)
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPdepend_per_locator(
+! CHECK: %[[A:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFdepend_per_locatorEa")
+! CHECK: %[[B:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFdepend_per_locatorEb")
+! CHECK: %[[C:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFdepend_per_locatorEc")
+! CHECK: %[[M:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFdepend_per_locatorEm")
+! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
+! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
+! CHECK: %[[J_LB32:.*]] = arith.constant 3 : i32
+! CHECK: %[[J_UB32:.*]] = fir.load %[[M]]#0 : !fir.ref<i32>
+! CHECK: %[[J_LB:.*]] = fir.convert %[[J_LB32]] : (i32) -> index
+! CHECK: %[[J_UB:.*]] = fir.convert %[[J_UB32]] : (i32) -> index
+! CHECK: %[[J_STEP:.*]] = arith.constant 1 : index
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
+! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
+! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
+! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
+! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
+! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
+! CHECK-SAME: (!fir.ref<i32>) -> !llvm.ptr
+! CHECK: omp.yield(%[[PTR_I]] : !llvm.ptr)
+! CHECK: } -> !omp.iterated<!llvm.ptr>
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[IV_J:.*]]: index) =
+! CHECK-SAME: (%[[J_LB]] to %[[J_UB]] step %[[J_STEP]]) {
+! CHECK: %[[V32_J:.*]] = fir.convert %[[IV_J]] : (index) -> i32
+! CHECK: fir.store %[[V32_J]] to %[[MEM_J:.*]] : !fir.ref<i32>
+! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[MEM_J]]
+! CHECK: %[[LD_J:.*]] = fir.load %[[DECL_J]]#0 : !fir.ref<i32>
+! CHECK: %[[IDX_J:.*]] = fir.convert %[[LD_J]] : (i32) -> i64
+! CHECK: %[[COOR_J:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %[[IDX_J]]
+! CHECK: %[[PTR_J:.*]] = fir.convert %[[COOR_J]]
+! CHECK-SAME: (!fir.ref<i32>) -> !llvm.ptr
+! CHECK: omp.yield(%[[PTR_J]] : !llvm.ptr)
+! CHECK: } -> !omp.iterated<!llvm.ptr>
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task depend(taskdependin -> %[[C]]#0 : !fir.ref<i32>,
+! CHECK-SAME: taskdependin -> %[[IT_I]] : !omp.iterated<!llvm.ptr>,
+! CHECK-SAME: taskdependin -> %[[IT_J]] : !omp.iterated<!llvm.ptr>) {
+
 subroutine task_depend_iterator_simple()
   integer, parameter :: n = 16
   integer :: a(n)
diff --git a/flang/test/Lower/OpenMP/iterator-empty-range.f90 b/flang/test/Lower/OpenMP/iterator-empty-range.f90
new file mode 100644
index 00000000000000..dcdd8752dea945
--- /dev/null
+++ b/flang/test/Lower/OpenMP/iterator-empty-range.f90
@@ -0,0 +1,282 @@
+! RUN: %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s
+
+! Empty ranges must produce zero entries and skip locator evaluation. Test
+! dynamic bounds and both step directions. Bounds equal to the initial value
+! must still produce one entry. Constant empty ranges are tested below.
+subroutine depend_empty_positive(a, m, d)
+  integer :: a(8), m, d
+  !$omp task depend(iterator(i=3:m), in: a(i/d))
+  !$omp end task
+end
+! CHECK-LABEL: define {{.*}} @depend_empty_positive_(
+! CHECK: [[M:%.*]] = load i32, ptr
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
+! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
+! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[SIZE:%.*]] = mul {{.*}}i64 [[COUNT]], 24
+! CHECK: [[LIST:%.*]] = {{.*}}call ptr @malloc(i64 [[SIZE]])
+! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
+! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32
+! CHECK: [[CONT]]:
+! CHECK: [[RUNTIME_COUNT:%.*]] = trunc i64 [[COUNT]] to i32
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}},
+! CHECK-SAME: i32 [[RUNTIME_COUNT]], ptr {{[^,)]*}}[[LIST]]
+
+subroutine affinity_empty_positive(a, m, d)
+  integer :: a(8), m, d
+  !$omp task affinity(iterator(i=3:m): a(i/d))
+  !$omp end task
+end
+! CHECK-LABEL: define {{.*}} @affinity_empty_positive_(
+! CHECK: [[M:%.*]] = load i32, ptr
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
+! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
+! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[LIST:%.*]] = alloca { i64, i64, i32 }, i64 [[COUNT]]
+! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
+! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32
+! CHECK: [[CONT]]:
+! CHECK: [[RUNTIME_COUNT:%.*]] = trunc i64 [[COUNT]] to i32
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}},
+! CHECK-SAME: i32 [[RUNTIME_COUNT]], ptr {{[^,)]*}}[[LIST]]
+
+subroutine depend_empty_negative(a, m, d)
+  integer :: a(8), m, d
+  !$omp task depend(iterator(i=3:m:-2), in: a(i/d))
+  !$omp end task
+end
+! CHECK-LABEL: define {{.*}} @depend_empty_negative_(
+! CHECK: [[M:%.*]] = load i32, ptr
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i65
+! CHECK: [[SPAN:%.*]] = sub nsw i65 3, [[WIDE]]
+! CHECK: [[EMPTY:%.*]] = icmp sgt i32 [[M]], 3
+! CHECK: [[HALF:%.*]] = lshr i65 [[SPAN]], 1
+! CHECK: [[HALF64:%.*]] = trunc {{.*}}i65 [[HALF]] to i64
+! CHECK: [[NONEMPTY:%.*]] = add i64 [[HALF64]], 1
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[SIZE:%.*]] = mul {{.*}}i64 [[COUNT]], 24
+! CHECK: [[LIST:%.*]] = {{.*}}call ptr @malloc(i64 [[SIZE]])
+! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
+! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32
+! CHECK: [[CONT]]:
+! CHECK: [[RUNTIME_COUNT:%.*]] = trunc i64 [[COUNT]] to i32
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}},
+! CHECK-SAME: i32 [[RUNTIME_COUNT]], ptr {{[^,)]*}}[[LIST]]
+
+subroutine affinity_empty_negative(a, m, d)
+  integer :: a(8), m, d
+  !$omp task affinity(iterator(i=3:m:-2): a(i/d))
+  !$omp end task
+end
+! CHECK-LABEL: define {{.*}} @affinity_empty_negative_(
+! CHECK: [[M:%.*]] = load i32, ptr
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i65
+! CHECK: [[SPAN:%.*]] = sub nsw i65 3, [[WIDE]]
+! CHECK: [[EMPTY:%.*]] = icmp sgt i32 [[M]], 3
+! CHECK: [[HALF:%.*]] = lshr i65 [[SPAN]], 1
+! CHECK: [[HALF64:%.*]] = trunc {{.*}}i65 [[HALF]] to i64
+! CHECK: [[NONEMPTY:%.*]] = add i64 [[HALF64]], 1
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[LIST:%.*]] = alloca { i64, i64, i32 }, i64 [[COUNT]]
+! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
+! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32
+! CHECK: [[CONT]]:
+! CHECK: [[RUNTIME_COUNT:%.*]] = trunc i64 [[COUNT]] to i32
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}},
+! CHECK-SAME: i32 [[RUNTIME_COUNT]], ptr {{[^,)]*}}[[LIST]]
+
+! A zero count in either retained dimension must suppress the entire locator.
+subroutine depend_empty_product(a, m, n, d)
+  integer :: a(8,8), m, n, d
+  !$omp task depend(iterator(i=3:m, j=1:n), in: a(i/d,j))
+  !$omp end task
+end
+! CHECK-LABEL: define {{.*}} @depend_empty_product_(
+! CHECK: [[M:%.*]] = load i32, ptr
+! CHECK: [[N:%.*]] = load i32, ptr
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
+! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
+! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[NCOUNT:%.*]] = {{.*}}call i32 @llvm.smax.i32(i32 [[N]], i32 0)
+! CHECK: [[N64:%.*]] = zext {{.*}}i32 [[NCOUNT]] to i64
+! CHECK: [[TOTAL:%.*]] = mul {{.*}}i64 [[COUNT]], [[N64]]
+! CHECK: [[SIZE:%.*]] = mul {{.*}}i64 [[TOTAL]], 24
+! CHECK: [[LIST:%.*]] = {{.*}}call ptr @malloc(i64 [[SIZE]])
+! CHECK: [[ZERO:%.*]] = icmp eq i64 [[TOTAL]], 0
+! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32
+! CHECK: [[CONT]]:
+! CHECK: [[RUNTIME_COUNT:%.*]] = trunc i64 [[TOTAL]] to i32
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}},
+! CHECK-SAME: i32 [[RUNTIME_COUNT]], ptr {{[^,)]*}}[[LIST]]
+
+subroutine affinity_empty_product(a, m, n, d)
+  integer :: a(8,8), m, n, d
+  !$omp task affinity(iterator(i=3:m, j=1:n): a(i/d,j))
+  !$omp end task
+end
+! CHECK-LABEL: define {{.*}} @affinity_empty_product_(
+! CHECK: [[M:%.*]] = load i32, ptr
+! CHECK: [[N:%.*]] = load i32, ptr
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
+! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
+! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[NCOUNT:%.*]] = {{.*}}call i32 @llvm.smax.i32(i32 [[N]], i32 0)
+! CHECK: [[N64:%.*]] = zext {{.*}}i32 [[NCOUNT]] to i64
+! CHECK: [[TOTAL:%.*]] = mul {{.*}}i64 [[COUNT]], [[N64]]
+! CHECK: [[LIST:%.*]] = alloca { i64, i64, i32 }, i64 [[TOTAL]]
+! CHECK: [[ZERO:%.*]] = icmp eq i64 [[TOTAL]], 0
+! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32
+! CHECK: [[CONT]]:
+! CHECK: [[RUNTIME_COUNT:%.*]] = trunc i64 [[TOTAL]] to i32
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}},
+! CHECK-SAME: i32 [[RUNTIME_COUNT]], ptr {{[^,)]*}}[[LIST]]
+
+! Unused iterator ranges must not affect locator counts.
+
+! The unused j range must not affect the number of dependences, including
+! when m < 3 makes that range empty.
+subroutine depend_unused_iterator(a, m)
+  integer :: a(2), m
+
+  !$omp task depend(iterator(i = 1:2, j = 3:m), in: a(i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @depend_unused_iterator_(
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 2,
+
+! Affinity uses the same per-locator selection and must also ignore empty j.
+subroutine affinity_unused_iterator(a, m)
+  integer :: a(2), m
+
+  !$omp task affinity(iterator(i = 1:2, j = 3:m): a(i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @affinity_unused_iterator_(
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 2,
+
+! Source references lost during folding must still control evaluation.
+
+! The folded-away i occurrence still makes an empty i range suppress the
+! locator, including its division by d. Test both consumers of omp.iterator.
+subroutine depend_folded_empty(a, m, d)
+  integer :: a(2), m, d
+  !$omp task depend(iterator(i = 1:m, j = 1:2), in: a(j/d + 0*i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @depend_folded_empty_(
+! CHECK: %[[M:.*]] = load i32,
+! CHECK: %[[N:.*]] = {{.*}}call i32 @llvm.smax.i32(i32 %[[M]], i32 0)
+! CHECK: %[[COUNT:.*]] = shl{{.*}} i32 %[[N]], 1
+! CHECK: %[[TOTAL:.*]] = zext i32 %[[COUNT]] to i64
+! CHECK: %[[SIZE:.*]] = mul{{.*}} i64 %[[TOTAL]], {{[0-9]+}}
+! CHECK: call ptr @malloc(i64 %[[SIZE]])
+! CHECK-NOT: sdiv
+! CHECK: %[[EMPTY:.*]] = icmp slt i32 %[[M]], 1
+! CHECK: br i1 %[[EMPTY]], label %[[EXIT:.*]], label %[[PRE:.*]]
+! CHECK: [[PRE]]:
+! CHECK: %[[D:.*]] = load i32,
+! CHECK: br label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32 %{{.*}}, %[[D]]
+! CHECK: [[EXIT]]:
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 %[[COUNT]],
+
+! A statically empty referenced range must also skip locator evaluation.
+subroutine depend_folded_zero(a, d)
+  integer :: a(2), d
+  !$omp task depend(iterator(i = 1:0, j = 1:2), in: a(j/d + 0*i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @depend_folded_zero_(
+! CHECK-NOT: sdiv
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 0,
+! CHECK-NOT: sdiv
+! CHECK: ret void
+
+subroutine affinity_folded_zero(a, d)
+  integer :: a(2), d
+  !$omp task affinity(iterator(i = 1:0, j = 1:2): a(j/d + 0*i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @affinity_folded_zero_(
+! CHECK-NOT: sdiv
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 0,
+! CHECK-NOT: sdiv
+! CHECK: ret void
+
+subroutine affinity_folded_empty(a, m, d)
+  integer :: a(2), m, d
+  !$omp task affinity(iterator(i = 1:m, j = 1:2): a(j/d + 0*i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @affinity_folded_empty_(
+! CHECK: %[[M:.*]] = load i32,
+! CHECK: %[[N:.*]] = {{.*}}call i32 @llvm.smax.i32(i32 %[[M]], i32 0)
+! CHECK: %[[COUNT:.*]] = shl{{.*}} i32 %[[N]], 1
+! CHECK: %[[TOTAL:.*]] = zext i32 %[[COUNT]] to i64
+! CHECK: alloca {{.*}}, i64 %[[TOTAL]]
+! CHECK-NOT: sdiv
+! CHECK: %[[EMPTY:.*]] = icmp slt i32 %[[M]], 1
+! CHECK: br i1 %[[EMPTY]], label %[[EXIT:.*]], label %[[PRE:.*]]
+! CHECK: [[PRE]]:
+! CHECK: %[[D:.*]] = load i32,
+! CHECK: br label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: sdiv i32 %{{.*}}, %[[D]]
+! CHECK: [[EXIT]]:
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 %[[COUNT]],
+
+! An unused j must not mask an empty retained i.
+subroutine depend_retained_empty(a, m, n)
+  integer :: a(8), m, n
+  !$omp task depend(iterator(i = 3:m, j = 1:n), in: a(i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @depend_retained_empty_(
+! CHECK: %[[EMPTY:.*]] = icmp slt i32 %{{.*}}, 3
+! CHECK: %[[TRIPS:.*]] = select i1 %[[EMPTY]], i64 0, i64 %{{.*}}
+! CHECK: %[[SIZE:.*]] = mul{{.*}} i64 %[[TRIPS]], {{[0-9]+}}
+! CHECK: call ptr @malloc(i64 %[[SIZE]])
+! CHECK: %[[ZERO:.*]] = icmp eq i64 %[[TRIPS]], 0
+! CHECK: br i1 %[[ZERO]], label %[[EXIT:.*]], label %[[BODY:.*]]
+! CHECK: [[BODY]]:
+! CHECK: [[EXIT]]:
+! CHECK: %[[COUNT:.*]] = trunc i64 %[[TRIPS]] to i32
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 %[[COUNT]],
diff --git a/flang/test/Lower/OpenMP/iterator-source-occurrences.f90 b/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
new file mode 100644
index 00000000000000..7387a544950663
--- /dev/null
+++ b/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
@@ -0,0 +1,149 @@
+! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s
+
+! Range selection follows resolved source occurrences, even when 0*i folds.
+! The enclosing i is distinct from the iterator i in the first clause.
+
+subroutine depend_folded(a, m, d, i)
+  integer :: a(2), m, d, i
+  !$omp task depend(iterator(i = 1:m, j = 1:2), &
+  !$omp& in: a(j/d + 0*i), a(1 + 0*i), a(j), a(1))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPdepend_folded(
+! CHECK: omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK: arith.divsi
+! CHECK: omp.yield
+! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.yield
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task
+! CHECK: return
+
+! The host i in the second clause must not be confused with iterator j.
+subroutine depend_shadowed(a, b, m, i)
+  integer :: a(2), b(2), m, i
+  !$omp task depend(iterator(i = 1:m), in: a(1 + 0*i)) &
+  !$omp& depend(iterator(j = 1:m), in: b(1 + 0*i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPdepend_shadowed(
+! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.yield
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task
+! CHECK: return
+
+subroutine affinity_folded(a, m, d, i)
+  integer :: a(2), m, d, i
+  !$omp task affinity(iterator(i = 1:m, j = 1:2): &
+  !$omp& a(j/d + 0*i), a(1 + 0*i), a(j), a(1))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPaffinity_folded(
+! CHECK: omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK: arith.divsi
+! CHECK: omp.yield
+! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.yield
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task
+! CHECK: return
+
+! The host i in the second task must not be confused with iterator j.
+! OpenMP 5.2 permits only one affinity clause per task directive.
+subroutine affinity_shadowed(a, b, m, i)
+  integer :: a(2), b(2), m, i
+  !$omp task affinity(iterator(i = 1:m): a(1 + 0*i))
+  !$omp end task
+  !$omp task affinity(iterator(j = 1:m): b(1 + 0*i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPaffinity_shadowed(
+! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.yield
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task
+! CHECK-NOT: omp.iterator
+! CHECK: return
+
+! These locators have equal folded designators but distinct source references.
+! The last one references no iterator; the middle one references both even
+! though all of its iterator references disappear during folding.
+subroutine depend_equal_designators(a, m)
+  integer :: a(2), m
+  !$omp task depend(iterator(i=1:m, j=1:2), in: a(1+0*j), a(1+0*j+0*i), a(1))
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPdepend_equal_designators(
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.iterator(%{{[^:]+}}: index, %{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task depend(
+
+subroutine affinity_equal_designators(a, m)
+  integer :: a(2), m
+  !$omp task affinity(iterator(i=1:m, j=1:2): a(1+0*j), a(1+0*j+0*i), a(1))
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPaffinity_equal_designators(
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.iterator(%{{[^:]+}}: index, %{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task affinity(
+
+! Identically spelled iterator names in different clauses have distinct scopes.
+subroutine depend_scoped_references(a, m)
+  integer :: a(2), m
+  !$omp task depend(iterator(i=1:m), in: a(1+0*i)) &
+  !$omp& depend(iterator(i=1:2), out: a(i))
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPdepend_scoped_references(
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.task depend(
+
+! Per-locator source metadata must also survive target clause decomposition.
+subroutine target_folded_reference(a, m)
+  integer :: a(2), m
+  !$omp target parallel do map(tofrom:a) depend(iterator(i=1:m), in: a(1+0*i))
+  do k=1,2
+    a(k)=k
+  end do
+  !$omp end target parallel do
+  !$omp target enter data map(to:a) depend(iterator(i=1:m), in: a(1+0*i))
+  !$omp target update to(a) depend(iterator(i=1:m), in: a(1+0*i))
+  !$omp target exit data map(from:a) depend(iterator(i=1:m), in: a(1+0*i))
+end
+! CHECK-LABEL: func.func @_QPtarget_folded_reference(
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.target
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.target_enter_data
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.target_update
+! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.yield
+! CHECK: omp.target_exit_data
diff --git a/flang/test/Lower/OpenMP/task-affinity.f90 b/flang/test/Lower/OpenMP/task-affinity.f90
index 0c185585627e27..17e26454add658 100644
--- a/flang/test/Lower/OpenMP/task-affinity.f90
+++ b/flang/test/Lower/OpenMP/task-affinity.f90
@@ -266,6 +266,112 @@ subroutine task_affinity_poly()
 
 ! Iterator tests
 
+! The unused j range must not suppress a(i) when m < 3.
+subroutine affinity_unused_iterator(m)
+  integer :: m
+  integer :: a(4)
+
+  !$omp task affinity(iterator(i = 1:2, j = 3:m) : a(i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPaffinity_unused_iterator(
+! CHECK: %[[A:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFaffinity_unused_iteratorEa")
+! CHECK: %[[M:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFaffinity_unused_iteratorEm")
+! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
+! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
+! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
+! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
+! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
+! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
+! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[SIZE_I:.*]] = arith.constant 4 : i64
+! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
+! CHECK-SAME: (!fir.ref<i32>) -> !fir.ref<i8>
+! CHECK: %[[ENTRY_I:.*]] = omp.affinity_entry %[[PTR_I]], %[[SIZE_I]]
+! CHECK: omp.yield(%[[ENTRY_I]] :
+! CHECK-SAME: !omp.affinity_entry_ty<!fir.ref<i8>, i64>)
+! CHECK: } -> !omp.iterated<!omp.affinity_entry_ty<!fir.ref<i8>, i64>>
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task affinity(%[[IT_I]] :
+! CHECK-SAME: !omp.iterated<!omp.affinity_entry_ty<!fir.ref<i8>, i64>>) {
+
+! Each locator uses its own iterator subset; c remains non-iterated.
+subroutine affinity_per_locator(m)
+  integer :: m
+  integer :: a(4), b(4), c
+
+  !$omp task affinity(iterator(i = 1:2, j = 3:m) : a(i), b(j), c)
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPaffinity_per_locator(
+! CHECK: %[[A:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFaffinity_per_locatorEa")
+! CHECK: %[[B:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFaffinity_per_locatorEb")
+! CHECK: %[[C:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFaffinity_per_locatorEc")
+! CHECK: %[[M:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFaffinity_per_locatorEm")
+! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
+! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
+! CHECK: %[[J_LB32:.*]] = arith.constant 3 : i32
+! CHECK: %[[J_UB32:.*]] = fir.load %[[M]]#0 : !fir.ref<i32>
+! CHECK: %[[J_LB:.*]] = fir.convert %[[J_LB32]] : (i32) -> index
+! CHECK: %[[J_UB:.*]] = fir.convert %[[J_UB32]] : (i32) -> index
+! CHECK: %[[J_STEP:.*]] = arith.constant 1 : index
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
+! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
+! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
+! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
+! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
+! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[SIZE_I:.*]] = arith.constant 4 : i64
+! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
+! CHECK-SAME: (!fir.ref<i32>) -> !fir.ref<i8>
+! CHECK: %[[ENTRY_I:.*]] = omp.affinity_entry %[[PTR_I]], %[[SIZE_I]]
+! CHECK: omp.yield(%[[ENTRY_I]] :
+! CHECK-SAME: !omp.affinity_entry_ty<!fir.ref<i8>, i64>)
+! CHECK: } -> !omp.iterated<!omp.affinity_entry_ty<!fir.ref<i8>, i64>>
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[IV_J:.*]]: index) =
+! CHECK-SAME: (%[[J_LB]] to %[[J_UB]] step %[[J_STEP]]) {
+! CHECK: %[[V32_J:.*]] = fir.convert %[[IV_J]] : (index) -> i32
+! CHECK: fir.store %[[V32_J]] to %[[MEM_J:.*]] : !fir.ref<i32>
+! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[MEM_J]]
+! CHECK: %[[LD_J:.*]] = fir.load %[[DECL_J]]#0 : !fir.ref<i32>
+! CHECK: %[[IDX_J:.*]] = fir.convert %[[LD_J]] : (i32) -> i64
+! CHECK: %[[COOR_J:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %[[IDX_J]]
+! CHECK: %[[SIZE_J:.*]] = arith.constant 4 : i64
+! CHECK: %[[PTR_J:.*]] = fir.convert %[[COOR_J]]
+! CHECK-SAME: (!fir.ref<i32>) -> !fir.ref<i8>
+! CHECK: %[[ENTRY_J:.*]] = omp.affinity_entry %[[PTR_J]], %[[SIZE_J]]
+! CHECK: omp.yield(%[[ENTRY_J]] :
+! CHECK-SAME: !omp.affinity_entry_ty<!fir.ref<i8>, i64>)
+! CHECK: } -> !omp.iterated<!omp.affinity_entry_ty<!fir.ref<i8>, i64>>
+! CHECK: %[[C_PTR:.*]] = fir.convert %[[C]]#0
+! CHECK-SAME: (!fir.ref<i32>) -> !fir.ref<i8>
+! CHECK: %[[C_ENTRY:.*]] = omp.affinity_entry %[[C_PTR]],
+! CHECK-NOT: omp.iterator
+! CHECK: omp.task affinity(%[[IT_I]] :
+! CHECK-SAME: !omp.iterated<!omp.affinity_entry_ty<!fir.ref<i8>, i64>>,
+! CHECK-SAME: %[[IT_J]] :
+! CHECK-SAME: !omp.iterated<!omp.affinity_entry_ty<!fir.ref<i8>, i64>>,
+! CHECK-SAME: %[[C_ENTRY]] : !omp.affinity_entry_ty<!fir.ref<i8>, i64>) {
+
 subroutine task_affinity_iterator_simple()
   integer, parameter :: n = 16
   integer :: a(n)
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index a46ae84df1784a..c7dd250e066612 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -5772,28 +5772,9 @@ LogicalResult IteratorOp::verify() {
              << "range argument type does not match corresponding IV type";
   }
 
-  for (auto [lb, ub, step] : llvm::zip_equal(
-           getLoopLowerBounds(), getLoopUpperBounds(), getLoopSteps())) {
+  for (Value step : getLoopSteps()) {
     if (matchPattern(step, m_Zero()))
       return emitOpError() << "loop step must not be zero";
-
-    IntegerAttr lbAttr;
-    IntegerAttr ubAttr;
-    IntegerAttr stepAttr;
-    if (!matchPattern(lb, m_Constant(&lbAttr)) ||
-        !matchPattern(ub, m_Constant(&ubAttr)) ||
-        !matchPattern(step, m_Constant(&stepAttr)))
-      continue;
-
-    const APInt &lbVal = lbAttr.getValue();
-    const APInt &ubVal = ubAttr.getValue();
-    const APInt &stepVal = stepAttr.getValue();
-    if (stepVal.isStrictlyPositive() && lbVal.sgt(ubVal))
-      return emitOpError() << "positive loop step requires lower bound to be "
-                              "less than or equal to upper bound";
-    if (stepVal.isNegative() && lbVal.slt(ubVal))
-      return emitOpError() << "negative loop step requires lower bound to be "
-                              "greater than or equal to upper bound";
   }
 
   YieldOp yield = getYieldOp();
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 1f0a09fad85a64..bf586abf6222f5 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -4929,34 +4929,6 @@ func.func @iterator_zero_step(%s2 : !llvm.struct<(ptr, i64)>) {
 
 // -----
 
-func.func @iterator_positive_step_wrong_direction(%s2 : !llvm.struct<(ptr, i64)>) {
-  %lb = arith.constant 1000 : index
-  %ub = arith.constant -1 : index
-  %st = arith.constant 10 : index
-
-  // expected-error at +1 {{positive loop step requires lower bound to be less than or equal to upper bound}}
-  %0 = omp.iterator(%iv: index) = (%lb to %ub step %st) {
-    omp.yield(%s2 : !llvm.struct<(ptr, i64)>)
-  } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
-  return
-}
-
-// -----
-
-func.func @iterator_negative_step_wrong_direction(%s2 : !llvm.struct<(ptr, i64)>) {
-  %lb = arith.constant -1000 : index
-  %ub = arith.constant 4 : index
-  %st = arith.constant -999 : index
-
-  // expected-error at +1 {{negative loop step requires lower bound to be greater than or equal to upper bound}}
-  %0 = omp.iterator(%iv: index) = (%lb to %ub step %st) {
-    omp.yield(%s2 : !llvm.struct<(ptr, i64)>)
-  } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
-  return
-}
-
-// -----
-
 func.func @iterator_missing_yield(%lb : index, %ub : index, %st : index) {
   // expected-error at +1 {{region must be terminated by omp.yield}}
   %0 = omp.iterator(%i: index) = (%lb to %ub step %st) {
diff --git a/mlir/test/Dialect/OpenMP/iterator-empty.mlir b/mlir/test/Dialect/OpenMP/iterator-empty.mlir
new file mode 100644
index 00000000000000..c1d8e27571e97d
--- /dev/null
+++ b/mlir/test/Dialect/OpenMP/iterator-empty.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-opt %s | mlir-opt | FileCheck %s
+
+// A range pointing away from its endpoint is valid and produces no entries.
+// CHECK-LABEL: func.func @empty_ranges
+func.func @empty_ranges(%x: !llvm.ptr) {
+  %c1 = arith.constant 1 : index
+  %c3 = arith.constant 3 : index
+  %neg = arith.constant -1 : index
+  // CHECK: omp.iterator
+  %positive = omp.iterator(%i: index) = (%c3 to %c1 step %c1) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  // CHECK: omp.iterator
+  %negative = omp.iterator(%i: index) = (%c1 to %c3 step %neg) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  return
+}
diff --git a/mlir/test/Target/LLVMIR/openmp-iterator-empty.mlir b/mlir/test/Target/LLVMIR/openmp-iterator-empty.mlir
new file mode 100644
index 00000000000000..794f1e2e50e2a9
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-iterator-empty.mlir
@@ -0,0 +1,54 @@
+// RUN: mlir-translate --mlir-to-llvmir %s | FileCheck %s
+
+// Inclusive ranges must be checked before dividing: (2 - 3) / 2 + 1
+// truncates to one even though the range is empty.
+llvm.func @empty_positive(%x: !llvm.ptr) {
+  %c2 = llvm.mlir.constant(2 : i64) : i64
+  %c3 = llvm.mlir.constant(3 : i64) : i64
+  %it = omp.iterator(%i: i64) = (%c3 to %c2 step %c2) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  omp.taskwait depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>)
+  llvm.return
+}
+
+// CHECK-LABEL: define void @empty_positive(
+// CHECK: call ptr @malloc(i64 0)
+// CHECK: icmp ult i64 %{{.*}}, 0
+// CHECK: call void @__kmpc_omp_taskwait_deps_51(
+// CHECK-SAME: i32 0, ptr %{{.*}}, i32 0, ptr null, i32 0)
+
+llvm.func @empty_negative(%x: !llvm.ptr) {
+  %c2 = llvm.mlir.constant(2 : i64) : i64
+  %c3 = llvm.mlir.constant(3 : i64) : i64
+  %step = llvm.mlir.constant(-2 : i64) : i64
+  %it = omp.iterator(%i: i64) = (%c2 to %c3 step %step) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  omp.taskwait depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>)
+  llvm.return
+}
+
+// CHECK-LABEL: define void @empty_negative(
+// CHECK: call ptr @malloc(i64 0)
+// CHECK: icmp ult i64 %{{.*}}, 0
+// CHECK: call void @__kmpc_omp_taskwait_deps_51(
+// CHECK-SAME: i32 0, ptr %{{.*}}, i32 0, ptr null, i32 0)
+
+// Two negative counts must not multiply into a nonempty iteration space.
+llvm.func @empty_product(%x: !llvm.ptr) {
+  %c1 = llvm.mlir.constant(1 : i64) : i64
+  %c3 = llvm.mlir.constant(3 : i64) : i64
+  %it = omp.iterator(%i: i64, %j: i64) =
+      (%c3 to %c1 step %c1, %c3 to %c1 step %c1) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  omp.taskwait depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>)
+  llvm.return
+}
+
+// CHECK-LABEL: define void @empty_product(
+// CHECK: call ptr @malloc(i64 0)
+// CHECK: icmp ult i64 %{{.*}}, 0
+// CHECK: call void @__kmpc_omp_taskwait_deps_51(
+// CHECK-SAME: i32 0, ptr %{{.*}}, i32 0, ptr null, i32 0)

>From 2f91a427b4eb695265f73ef7774434e18319558d Mon Sep 17 00:00:00 2001
From: "Chi-Chun, Chen" <chichun.chen at hpe.com>
Date: Mon, 5 Oct 2026 01:01:06 -0500
Subject: [PATCH 2/3] Fix per-locator iterator lowering regressions

Reuse ordinary locator lowering inside depend and affinity iterators to
preserve component and vector-subscript dependence support. Keep locator
evaluation and temporary cleanup inside the iterator region so empty
selected ranges suppress evaluation. Preserve affinity section lengths.

Reject iterated dependences on unsupported target-data operations during
translation.

Bind source-occurrence checks to each locator's ranges and yielded value.
Add locator, wide-range, empty-range, and target-data diagnostic coverage,
plus locators whose lowering adds control flow to the iterator region
(LEN_TRIM, allocatable function results, and SUM inlined at -O1).
---
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |  84 ++----
 flang/lib/Lower/OpenMP/Utils.cpp              | 111 --------
 flang/lib/Lower/OpenMP/Utils.h                |   9 -
 .../OpenMP/iterator-locator-control-flow.f90  | 104 ++++++++
 flang/test/Lower/OpenMP/depend-iterator.f90   |  62 ++---
 flang/test/Lower/OpenMP/iterator-locators.f90 | 246 ++++++++++++++++++
 .../OpenMP/iterator-source-occurrences.f90    |  86 +++++-
 .../Lower/OpenMP/iterator-target-data.f90     |  66 +++++
 flang/test/Lower/OpenMP/task-affinity.f90     |  73 +++---
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      |   3 +-
 .../Target/LLVMIR/openmp-iterator-wide.mlir   |  32 +++
 mlir/test/Target/LLVMIR/openmp-todo.mlir      |  47 ++++
 12 files changed, 661 insertions(+), 262 deletions(-)
 create mode 100644 flang/test/Integration/OpenMP/iterator-locator-control-flow.f90
 create mode 100644 flang/test/Lower/OpenMP/iterator-locators.f90
 create mode 100644 flang/test/Lower/OpenMP/iterator-target-data.f90

diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 6d235c4279171d..e99c803fff5d71 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1048,9 +1048,29 @@ bool ClauseProcessor::processAffinity(
 
         TodoLocators(clauseLocation, objects);
 
-        for (const omp::Object &object : objects) {
+        auto genEntry = [&](const omp::Object &object,
+                            lower::StatementContext &localStmtCtx) {
+          mlir::Value addr =
+              genAffinityAddr(converter, object, localStmtCtx, clauseLocation);
           llvm::SmallVector<mlir::Value> bounds;
           std::stringstream asFortran;
+          fir::factory::AddrAndBoundsInfo info =
+              lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
+                                                    mlir::omp::MapBoundsType>(
+                  converter, builder, semaCtx, localStmtCtx, *object.sym(),
+                  object.ref(), clauseLocation, asFortran, bounds,
+                  treatIndexAsSection);
+          hlfir::Entity entity{info.addr};
+          mlir::Value len =
+              object.ref() && object.ref()->Rank() == 0
+                  ? genElementSizeInBytes(builder, clauseLocation,
+                                          builder.getDataLayout(), entity)
+                  : genAffinityLen(builder, clauseLocation,
+                                   builder.getDataLayout(), entity, bounds);
+          return makeAffinityEntry(builder, clauseLocation, entryTy, addr, len);
+        };
+
+        for (const omp::Object &object : objects) {
           llvm::SmallVector<IteratorRange> objectRanges =
               getIteratorRangesForObject(object, iteratorRanges);
           if (!objectRanges.empty()) {
@@ -1059,43 +1079,11 @@ bool ClauseProcessor::processAffinity(
                 [&](fir::FirOpBuilder &builder, mlir::Location loc,
                     llvm::ArrayRef<mlir::Value> /*ivs*/) -> mlir::Value {
                   lower::StatementContext iterStmtCtx;
-
-                  if (std::optional<llvm::SmallVector<mlir::Value>>
-                          loweredIndices = getIteratorElementIndices(
-                              converter, object, iterStmtCtx, loc)) {
-                    const Fortran::semantics::Symbol *sym = object.sym();
-                    assert(sym && "expected symbol for iterator object");
-                    fir::factory::AddrAndBoundsInfo info =
-                        Fortran::lower::getDataOperandBaseAddr(
-                            converter, builder, *sym, loc,
-                            /*unwrapFirBox=*/false);
-                    hlfir::Entity entity{info.addr};
-                    mlir::Value iteratedAddr = genIteratorCoordinate(
-                        converter, entity, *loweredIndices, loc);
-                    mlir::Value len = genElementSizeInBytes(
-                        builder, loc, builder.getDataLayout(), entity);
-                    return makeAffinityEntry(builder, loc, entryTy,
-                                             iteratedAddr, len);
-                  }
-
-                  TODO(loc, "object type not supported by iterator modifier");
+                  return genEntry(object, iterStmtCtx);
                 });
             result.iterated.push_back(iterHandle);
           } else {
-            mlir::Value addr =
-                genAffinityAddr(converter, object, stmtCtx, clauseLocation);
-            // get hlfir.declare for length calculation
-            fir::factory::AddrAndBoundsInfo info =
-                lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
-                                                      mlir::omp::MapBoundsType>(
-                    converter, builder, semaCtx, stmtCtx, *object.sym(),
-                    object.ref(), clauseLocation, asFortran, bounds,
-                    treatIndexAsSection);
-            mlir::Value len =
-                genAffinityLen(builder, clauseLocation, builder.getDataLayout(),
-                               hlfir::Entity{info.addr}, bounds);
-            result.affinityVars.push_back(
-                makeAffinityEntry(builder, clauseLocation, entryTy, addr, len));
+            result.affinityVars.push_back(genEntry(object, stmtCtx));
           }
         }
 
@@ -1519,29 +1507,9 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
             [&](fir::FirOpBuilder &builder, mlir::Location loc,
                 llvm::ArrayRef<mlir::Value> /*ivs*/) -> mlir::Value {
               lower::StatementContext iterStmtCtx;
-              if (std::optional<llvm::SmallVector<mlir::Value>> loweredIndices =
-                      getIteratorElementIndices(converter, object, iterStmtCtx,
-                                                loc)) {
-                const Fortran::semantics::Symbol *sym = object.sym();
-                assert(sym && "expected symbol for iterator object");
-                // genDependVar is not reused here: getIteratorElementIndices
-                // has already lowered each subscript to a FIR-level index
-                // value, so the element coordinate is computed directly from
-                // the base address and those indices rather than re-lowering
-                // the whole designator.
-                fir::factory::AddrAndBoundsInfo info =
-                    Fortran::lower::getDataOperandBaseAddr(
-                        converter, builder, *sym, loc,
-                        /*unwrapFirBox=*/false);
-                hlfir::Entity entity{info.addr};
-                mlir::Value iteratedAddr = genIteratorCoordinate(
-                    converter, entity, *loweredIndices, loc);
-                // Convert to !llvm.ptr for the omp.yield
-                return fir::ConvertOp::create(builder, loc, ptrTy,
-                                              iteratedAddr);
-              }
-
-              TODO(loc, "object type not supported by iterator modifier");
+              mlir::Value addr =
+                  genDependVar(object, converter.getSymbolMap(), iterStmtCtx);
+              return fir::ConvertOp::create(builder, loc, ptrTy, addr);
             });
         result.dependIterated.push_back(iterHandle);
         result.dependIteratedKinds.push_back(dependTypeOperand);
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index f53429a615a391..9e37c02eac3f1f 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -1288,117 +1288,6 @@ mlir::FlatSymbolRefAttr resolveMapperId(
   return mapperId;
 }
 
-// Build the array coordinate for an object that uses iterator variables.
-// If the object is a section, use the first element of that section
-// as the coordinate. Currently only support top-level ArrayRef designators.
-//
-// Examples:
-//   a(i, j)       -> coordinates for a(i, j)
-//   a(i:i+1, j+2) -> coordinates for a(i, j+2)
-std::optional<llvm::SmallVector<mlir::Value>> getIteratorElementIndices(
-    Fortran::lower::AbstractConverter &converter, const omp::Object &object,
-    Fortran::lower::StatementContext &stmtCtx, mlir::Location loc) {
-  const std::optional<ExprTy> &ref = object.ref();
-  assert(ref && "expected iterator-dependent object to have a reference");
-
-  std::optional<Fortran::evaluate::DataRef> dataRef =
-      Fortran::evaluate::ExtractDataRef(*ref);
-  if (!dataRef)
-    return std::nullopt;
-  const auto *arrayRef = std::get_if<Fortran::evaluate::ArrayRef>(&dataRef->u);
-  if (!arrayRef || arrayRef->subscript().empty())
-    return std::nullopt;
-
-  auto &builder = converter.getFirOpBuilder();
-  const Fortran::semantics::Symbol *sym = object.sym();
-  assert(sym && "expected symbol for iterator-dependent object");
-  fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*sym);
-  mlir::Value one =
-      builder.createIntegerConstant(loc, builder.getIndexType(), 1);
-  llvm::SmallVector<mlir::Value> indices;
-  indices.reserve(arrayRef->subscript().size());
-
-  for (const auto &[dim, subscript] : llvm::enumerate(arrayRef->subscript())) {
-    mlir::Value idx;
-    if (const auto *triplet =
-            std::get_if<Fortran::evaluate::Triplet>(&subscript.u)) {
-      // Sections use the first element of the section as the base address, so
-      // the coordinate for this dimension comes from the triplet lower bound.
-      std::optional<
-          Fortran::evaluate::Expr<Fortran::evaluate::SubscriptInteger>>
-          lowerBound = triplet->lower();
-      if (!lowerBound) {
-        // Get lower bound if not provided by user.
-        // For example: !$omp task affinity(iterator(i = 1:n, j = 1:m) : a(:i+1,
-        // j+2))
-        idx = fir::factory::readLowerBound(builder, loc, dataExv, dim, one);
-      } else {
-        idx = fir::getBase(
-            converter.genExprValue(toEvExpr(*lowerBound), stmtCtx, &loc));
-      }
-    } else {
-      // Not handling vector subscripts for now.
-      if (subscript.Rank() > 0)
-        return std::nullopt;
-
-      const auto *indirect =
-          std::get_if<Fortran::evaluate::IndirectSubscriptIntegerExpr>(
-              &subscript.u);
-      assert(indirect && "expected non-triplet subscript");
-
-      // Scalar subscripts, including reordered indices and expressions like
-      // i+1 or j+2, lower directly through expression lowering.
-      idx = fir::getBase(
-          converter.genExprValue(toEvExpr(indirect->value()), stmtCtx, &loc));
-    }
-    indices.push_back(idx);
-  }
-
-  return indices;
-}
-
-// Build the element address for an iterator-dependent affinity object from a
-// base entity and lowered indices.
-mlir::Value genIteratorCoordinate(Fortran::lower::AbstractConverter &converter,
-                                  hlfir::Entity entity,
-                                  llvm::ArrayRef<mlir::Value> ivs,
-                                  mlir::Location loc) {
-  auto &builder = converter.getFirOpBuilder();
-  mlir::Value base = entity.getBase();
-
-  // If base is a reference-to-box, load it so array_coor sees the box value
-  if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(base.getType())) {
-    if (mlir::isa<fir::BoxType>(refTy.getEleTy()))
-      base = fir::LoadOp::create(builder, loc, base);
-  }
-
-  // Build shape from the entity extents
-  mlir::Value shape;
-  auto extents = hlfir::genExtentsVector(loc, builder, entity);
-  assert(extents.size() == ivs.size() &&
-         "expected the number of extents and iteration variables to match for "
-         "iterator");
-  if (entity.mayHaveNonDefaultLowerBounds()) {
-    llvm::SmallVector<mlir::Value> lowerBounds;
-    lowerBounds.reserve(ivs.size());
-    for (unsigned dim = 0; dim < ivs.size(); ++dim)
-      lowerBounds.push_back(hlfir::genLBound(loc, builder, entity, dim));
-    shape = builder.genShape(loc, lowerBounds, extents);
-  } else {
-    shape = fir::ShapeOp::create(builder, loc, extents);
-  }
-
-  mlir::Type elementToRefTy =
-      fir::ReferenceType::get(entity.getFortranElementType());
-
-  return fir::ArrayCoorOp::create(builder, loc, elementToRefTy,
-                                  /*memref=*/base,
-                                  /*shape=*/shape,
-                                  /*slice=*/mlir::Value{},
-                                  /*indices=*/ivs,
-                                  /*typeparams=*/mlir::ValueRange{});
-}
-
 // ---------------------------------------------------------------------------
 // OpenMP variant-matching context construction from an MLIR module
 // ---------------------------------------------------------------------------
diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h
index 3228905fd57c48..c769380aabbb01 100644
--- a/flang/lib/Lower/OpenMP/Utils.h
+++ b/flang/lib/Lower/OpenMP/Utils.h
@@ -231,11 +231,6 @@ getIteratorRangesForObject(const omp::Object &object,
 void defaultMangler(Fortran::lower::AbstractConverter &converter,
                     std::string &mapperIdName, llvm::StringRef memberName);
 
-mlir::Value genIteratorCoordinate(Fortran::lower::AbstractConverter &converter,
-                                  hlfir::Entity entity,
-                                  llvm::ArrayRef<mlir::Value> ivs,
-                                  mlir::Location loc);
-
 /// Resolve the declare mapper symbol to attach to a mapped object.
 ///
 /// The default mapper path first looks for a user-defined mapper. If none
@@ -257,10 +252,6 @@ mlir::FlatSymbolRefAttr resolveMapperId(
     const omp::Object &object, llvm::StringRef mapperIdName,
     mlir::omp::ClauseMapFlags mapTypeBits, llvm::omp::Directive directive);
 
-std::optional<llvm::SmallVector<mlir::Value>> getIteratorElementIndices(
-    Fortran::lower::AbstractConverter &converter, const omp::Object &object,
-    Fortran::lower::StatementContext &stmtCtx, mlir::Location loc);
-
 /// Walk the already-emitted MLIR parent operations starting from \p op and
 /// collect the implied OpenMP construct traits in outermost-to-innermost
 /// order. Used by metadirective lowering and declare-variant call resolution
diff --git a/flang/test/Integration/OpenMP/iterator-locator-control-flow.f90 b/flang/test/Integration/OpenMP/iterator-locator-control-flow.f90
new file mode 100644
index 00000000000000..11a79a353ef003
--- /dev/null
+++ b/flang/test/Integration/OpenMP/iterator-locator-control-flow.f90
@@ -0,0 +1,104 @@
+!===----------------------------------------------------------------------===!
+! This directory can be used to add Integration tests involving multiple
+! stages of the compiler (for eg. from Fortran to LLVM IR). It should not
+! contain executable tests. We should only add tests here sparingly and only
+! if there is no other way to test. Repeat this message in each test that is
+! added to this directory and sub-directories.
+!===----------------------------------------------------------------------===!
+
+! Iterator locators are lowered inside the omp.iterator region. Lowering and
+! later passes can add control flow there, which only shows up after
+! control-flow conversion, so these cases are checked through LLVM IR.
+
+! RUN: %flang_fc1 -emit-llvm -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s
+! RUN: %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s --check-prefix=O1
+
+module m
+contains
+  function fa(i) result(r)
+    integer, intent(in) :: i
+    integer, allocatable :: r
+    allocate(r)
+    r = i + 1
+  end function
+end module
+
+! LEN_TRIM in the section bound lowers to a loop.
+subroutine depend_section_len_trim(a, s, n)
+  integer :: a(10), n
+  character(*) :: s
+  !$omp task depend(iterator(i=1:n), in: a(i:len_trim(s)))
+  !$omp end task
+end
+
+! CHECK-LABEL: define void @depend_section_len_trim_(
+! CHECK-SAME: ptr {{[^%]*}}%[[A:[0-9]+]],
+! CHECK: omp.iterator.region:
+! CHECK: phi i64
+! CHECK: getelementptr [10 x i32], ptr %[[A]]
+! CHECK: %[[P:.*]] = load ptr, ptr
+! CHECK: omp.iterator.region.cont:
+! CHECK: %[[PI:.*]] = ptrtoint ptr %[[P]] to i64
+! CHECK: store i64 %[[PI]], ptr
+! CHECK: br label %omp_dep_iterator.inc
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+
+! The affinity length spans the section up to LEN_TRIM(s).
+subroutine affinity_section_len_trim(a, s, n)
+  integer :: a(10), n
+  character(*) :: s
+  !$omp task affinity(iterator(i=1:n): a(i:len_trim(s)))
+  !$omp end task
+end
+
+! CHECK-LABEL: define void @affinity_section_len_trim_(
+! CHECK-SAME: ptr {{[^%]*}}%[[A:[0-9]+]],
+! CHECK: omp.iterator.region:
+! CHECK: phi i64
+! CHECK: getelementptr [10 x i32], ptr %[[A]]
+! CHECK: %[[P:.*]] = load ptr, ptr
+! CHECK: %[[LEN:.*]] = mul i64 %{{.*}}, 4
+! CHECK: omp.iterator.region.cont:
+! CHECK: %[[PI:.*]] = ptrtoint ptr %[[P]] to i64
+! CHECK: store i64 %[[PI]], ptr
+! CHECK: store i64 %[[LEN]], ptr
+! CHECK: br label %omp_iterator.inc
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+
+! The allocatable function result is freed conditionally.
+subroutine depend_alloc_result(a, n)
+  use m
+  integer :: a(10), n
+  !$omp task depend(iterator(i=1:n), in: a(i:fa(i)))
+  !$omp end task
+end
+
+! CHECK-LABEL: define void @depend_alloc_result_(
+! CHECK-SAME: ptr {{[^%]*}}%[[A:[0-9]+]],
+! CHECK: omp.iterator.region:
+! CHECK: call void @_QMmPfa(
+! CHECK: getelementptr [10 x i32], ptr %[[A]]
+! CHECK: %[[P:.*]] = load ptr, ptr
+! CHECK: omp.iterator.region{{[0-9]+}}:
+! CHECK: call void @free(
+! CHECK: omp.iterator.region.cont:
+! CHECK: %[[PI:.*]] = ptrtoint ptr %[[P]] to i64
+! CHECK: store i64 %[[PI]], ptr
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+
+! At -O1, SUM is inlined into the region of a folded locator.
+subroutine depend_folded_sum(a, v, n)
+  integer :: a(10), v(3), n
+  !$omp task depend(iterator(i=1:n), in: a(sum(v)+0*i))
+  !$omp end task
+end
+
+! O1-LABEL: define void @depend_folded_sum_(
+! O1-SAME: ptr {{[^%]*}}%[[A:[0-9]+]], ptr {{[^%]*}}%[[V:[0-9]+]],
+! O1: omp.iterator.region{{[0-9]*}}:
+! O1: getelementptr {{.*}}ptr %[[V]]
+! O1: omp.iterator.region{{[0-9]*}}:
+! O1: getelementptr {{.*}}ptr %[[A]]
+! O1: call i32 @__kmpc_omp_task_with_deps(
diff --git a/flang/test/Lower/OpenMP/depend-iterator.f90 b/flang/test/Lower/OpenMP/depend-iterator.f90
index 47431fce1b1a77..bd83fdc8a01ad0 100644
--- a/flang/test/Lower/OpenMP/depend-iterator.f90
+++ b/flang/test/Lower/OpenMP/depend-iterator.f90
@@ -36,7 +36,7 @@ subroutine depend_unused_iterator(m)
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
-! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[COOR_I:.*]] = hlfir.designate %[[A]]#0 (%[[IDX_I]])
 ! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
 ! CHECK-SAME: (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK: omp.yield(%[[PTR_I]] : !llvm.ptr)
@@ -80,7 +80,7 @@ subroutine depend_per_locator(m)
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
-! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[COOR_I:.*]] = hlfir.designate %[[A]]#0 (%[[IDX_I]])
 ! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
 ! CHECK-SAME: (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK: omp.yield(%[[PTR_I]] : !llvm.ptr)
@@ -92,7 +92,7 @@ subroutine depend_per_locator(m)
 ! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[MEM_J]]
 ! CHECK: %[[LD_J:.*]] = fir.load %[[DECL_J]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_J:.*]] = fir.convert %[[LD_J]] : (i32) -> i64
-! CHECK: %[[COOR_J:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %[[IDX_J]]
+! CHECK: %[[COOR_J:.*]] = hlfir.designate %[[B]]#0 (%[[IDX_J]])
 ! CHECK: %[[PTR_J:.*]] = fir.convert %[[COOR_J]]
 ! CHECK-SAME: (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK: omp.yield(%[[PTR_J]] : !llvm.ptr)
@@ -121,8 +121,7 @@ subroutine task_depend_iterator_simple()
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]] uniq_name("_QQ{{.*}}.omp.iter")
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%[[IV_I64]])
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -151,8 +150,7 @@ subroutine task_depend_iterator_2d()
 ! CHECK:   %[[IV0_I64:.*]] = fir.convert %[[IV0_LD]] : (i32) -> i64
 ! CHECK:   %[[IV1_LD:.*]] = fir.load %[[IV1_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV1_I64:.*]] = fir.convert %[[IV1_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c4, %c6 : (index, index) -> !fir.shape<2>
-! CHECK:   %[[COOR:.*]] = fir.array_coor %{{.*}}(%[[SHAPE]]) %[[IV0_I64]], %[[IV1_I64]] : (!fir.ref<!fir.array<4x6xi32>>, !fir.shape<2>, i64, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %{{.*}} (%[[IV0_I64]], %[[IV1_I64]])
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -209,12 +207,12 @@ subroutine task_depend_iterator_multi_obj()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_multi_objEa")
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_multi_objEb")
 ! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   %[[PTR1:.*]] = fir.convert %[[COOR1]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR1]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   %[[PTR2:.*]] = fir.convert %[[COOR2]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR2]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -243,13 +241,13 @@ subroutine task_depend_iterator_expr_subscript()
 ! CHECK:   %[[IV1_DECL:.*]]:2 = hlfir.declare %[[IV1_MEM]]
 ! CHECK:   %[[IV0_LD:.*]] = fir.load %[[IV0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C1_I32:.*]] = arith.constant 1 : i32
-! CHECK:   %[[SUB:.*]] = arith.subi %[[IV0_LD]], %[[C1_I32]] : i32
+! CHECK:   %[[SUB:.*]] = arith.subi %[[IV0_LD]], %[[C1_I32]] overflow<nsw> : i32
 ! CHECK:   %[[NOREASSOC:.*]] = hlfir.no_reassoc %[[SUB]] : i32
-! CHECK:   %[[MUL:.*]] = arith.muli %{{.*}}, %[[NOREASSOC]] : i32
+! CHECK:   %[[MUL:.*]] = arith.muli %{{.*}}, %[[NOREASSOC]] overflow<nsw> : i32
 ! CHECK:   %[[IV1_LD:.*]] = fir.load %[[IV1_DECL]]#0 : !fir.ref<i32>
-! CHECK:   %[[ADD:.*]] = arith.addi %[[MUL]], %[[IV1_LD]] : i32
+! CHECK:   %[[ADD:.*]] = arith.addi %[[MUL]], %[[IV1_LD]] overflow<nsw> : i32
 ! CHECK:   %[[IDX:.*]] = fir.convert %[[ADD]] : (i32) -> i64
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%[[IDX]])
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -270,12 +268,12 @@ subroutine task_depend_multi_iter_clauses()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_multi_iter_clausesEa")
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_multi_iter_clausesEb")
 ! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   %[[PTR1:.*]] = fir.convert %[[COOR1]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR1]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   %[[PTR2:.*]] = fir.convert %[[COOR2]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR2]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -318,7 +316,7 @@ subroutine task_depend_iterator_mixed_within_clause()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_mixed_within_clauseEa")
 ! CHECK: %[[A1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})  : (!fir.ref<!fir.array<16xi32>>, index) -> !fir.ref<i32>
 ! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -346,8 +344,7 @@ subroutine target_depend_iterator()
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%[[IV_I64]])
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -373,15 +370,15 @@ subroutine target_depend_iterator_multi()
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_depend_iterator_multiEb")
 ! CHECK: %[[C:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_depend_iterator_multiEc")
 ! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[IT3:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR3:.*]] = fir.array_coor %[[C]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR3:.*]] = hlfir.designate %[[C]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) bounds({{.*}}) name("a") -> !fir.ref<!fir.array<8xi32>>
@@ -409,8 +406,7 @@ subroutine target_enter_data_depend_iterator()
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%[[IV_I64]])
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -440,11 +436,11 @@ subroutine target_enter_data_depend_iterator_expr()
 ! CHECK:   %[[IV0_LD:.*]] = fir.load %[[IV0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[SUB:.*]] = arith.subi %[[IV0_LD]], %{{.*}} : i32
 ! CHECK:   %[[NOREASSOC:.*]] = hlfir.no_reassoc %[[SUB]] : i32
-! CHECK:   %[[MUL:.*]] = arith.muli %{{.*}}, %[[NOREASSOC]] : i32
+! CHECK:   %[[MUL:.*]] = arith.muli %{{.*}}, %[[NOREASSOC]] overflow<nsw> : i32
 ! CHECK:   %[[IV1_LD:.*]] = fir.load %[[IV1_DECL]]#0 : !fir.ref<i32>
-! CHECK:   %[[ADD:.*]] = arith.addi %[[MUL]], %[[IV1_LD]] : i32
+! CHECK:   %[[ADD:.*]] = arith.addi %[[MUL]], %[[IV1_LD]] overflow<nsw> : i32
 ! CHECK:   %[[IDX:.*]] = fir.convert %[[ADD]] : (i32) -> i64
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%[[IDX]])
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(to) capture(ByRef) bounds({{.*}}) name("a") -> !fir.ref<!fir.array<16xi32>>
@@ -470,8 +466,7 @@ subroutine target_exit_data_depend_iterator()
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%[[IV_I64]])
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -497,11 +492,11 @@ subroutine target_exit_data_depend_iterator_multi()
 ! CHECK: %[[CM1_I32:.*]] = arith.constant -1 : i32
 ! CHECK: %[[STEP:.*]] = fir.convert %[[CM1_I32]] : (i32) -> index
 ! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
-! CHECK:   %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
-! CHECK:   %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(from) capture(ByRef) bounds({{.*}}) name("a") -> !fir.ref<!fir.array<16xi32>>
@@ -528,8 +523,7 @@ subroutine target_update_depend_iterator()
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%[[IV_I64]])
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -554,11 +548,11 @@ subroutine target_update_depend_iterator_multi()
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_update_depend_iterator_multiEb")
 ! CHECK: %[[X:.*]]:2 = hlfir.declare %{{.*}} uniq_name("_QFtarget_update_depend_iterator_multiEx")
 ! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(to) capture(ByRef) bounds({{.*}}) name("a") -> !fir.ref<!fir.array<8xi32>>
diff --git a/flang/test/Lower/OpenMP/iterator-locators.f90 b/flang/test/Lower/OpenMP/iterator-locators.f90
new file mode 100644
index 00000000000000..2ed1ce918eec17
--- /dev/null
+++ b/flang/test/Lower/OpenMP/iterator-locators.f90
@@ -0,0 +1,246 @@
+! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s
+! RUN: %flang_fc1 -emit-llvm -fopenmp -fopenmp-version=52 -o /dev/null %s
+! RUN: %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 -o - %s \
+! RUN:   | FileCheck %s --check-prefix=LLVM
+
+! Folded and live iterator references must use ordinary locator semantics.
+! All designator evaluation belongs inside the selected iterator region.
+
+subroutine depend_component(a, m, d)
+  type t
+    integer :: field
+  end type
+  type(t) :: a(8)
+  integer :: m, d
+  !$omp task depend(iterator(i=1:m), in: &
+  !$omp& a(1+0*i)%field, a(i/d)%field)
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPdepend_component(
+! CHECK: %[[BASE:.*]]:2 = hlfir.declare %arg0
+! CHECK-NOT: arith.divsi
+! CHECK: %[[FOLDED:.*]] = omp.iterator(
+! CHECK: %[[ELEM:.*]] = hlfir.designate %[[BASE]]#0 (
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[ELEM]]{"field"}
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
+! CHECK: %[[LIVE:.*]] = omp.iterator(
+! CHECK: arith.divsi
+! CHECK: %[[ELEM:.*]] = hlfir.designate %[[BASE]]#0 (
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[ELEM]]{"field"}
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
+! CHECK: omp.task depend(
+! CHECK-SAME: %[[FOLDED]] :
+! CHECK-SAME: %[[LIVE]] :
+
+subroutine depend_vector(a, m, d)
+  integer :: a(8)
+  integer :: m, d
+  !$omp task depend(iterator(i=1:m), in: &
+  !$omp& a([1+0*i]), a([i/d]))
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPdepend_vector(
+! CHECK: %[[BASE:.*]]:2 = hlfir.declare %arg0
+! CHECK-NOT: arith.divsi
+! CHECK: %[[FOLDED:.*]] = omp.iterator(
+! CHECK: %[[INDEX:.*]] = fir.load {{.*}} : !fir.ref<i64>
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[BASE]]#0 (%[[INDEX]])
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
+! CHECK: %[[LIVE:.*]] = omp.iterator(
+! CHECK: arith.divsi
+! CHECK: %[[TMP:.*]] = hlfir.as_expr
+! CHECK: %[[INDEX:.*]] = hlfir.apply %[[TMP]],
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[BASE]]#0 (%[[INDEX]])
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: hlfir.destroy %[[TMP]]
+! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
+! CHECK: omp.task depend(
+! CHECK-SAME: %[[FOLDED]] :
+! CHECK-SAME: %[[LIVE]] :
+
+subroutine depend_section(x, m, d)
+  type t
+    integer :: a(8)
+  end type
+  type(t) :: x
+  integer :: m, d
+  !$omp task depend(iterator(i=1:m), in: &
+  !$omp& x%a(1:2+0*i), x%a(i/d:i/d+1))
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPdepend_section(
+! CHECK: %[[BASE:.*]]:2 = hlfir.declare %arg0
+! CHECK-NOT: arith.divsi
+! CHECK: %[[FOLDED:.*]] = omp.iterator(
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[BASE]]#0{"a"}
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
+! CHECK: %[[LIVE:.*]] = omp.iterator(
+! CHECK: arith.divsi
+! CHECK: %[[BOX:.*]] = hlfir.designate %[[BASE]]#0{"a"}
+! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]]
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
+! CHECK: omp.task depend(
+! CHECK-SAME: %[[FOLDED]] :
+! CHECK-SAME: %[[LIVE]] :
+
+subroutine affinity_component(a, m, d)
+  type t
+    integer :: field
+  end type
+  type(t) :: a(8)
+  integer :: m, d
+  !$omp task affinity(iterator(i=1:m): &
+  !$omp& a(1+0*i)%field, a(i/d)%field)
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPaffinity_component(
+! CHECK: %[[BASE:.*]]:2 = hlfir.declare %arg0
+! CHECK-NOT: arith.divsi
+! CHECK: %[[FOLDED:.*]] = omp.iterator(
+! CHECK: %[[ELEM:.*]] = hlfir.designate %[[BASE]]#0 (
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[ELEM]]{"field"}
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: %[[ENTRY:.*]] = omp.affinity_entry %[[PTR]],
+! CHECK: omp.yield(%[[ENTRY]] :
+! CHECK: %[[LIVE:.*]] = omp.iterator(
+! CHECK: arith.divsi
+! CHECK: %[[ELEM:.*]] = hlfir.designate %[[BASE]]#0 (
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[ELEM]]{"field"}
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: %[[ENTRY:.*]] = omp.affinity_entry %[[PTR]],
+! CHECK: omp.yield(%[[ENTRY]] :
+! CHECK: omp.task affinity(
+! CHECK-SAME: %[[FOLDED]] :
+! CHECK-SAME: %[[LIVE]] :
+
+subroutine affinity_section(x, m, d)
+  type t
+    integer :: a(8)
+  end type
+  type(t) :: x
+  integer :: m, d
+  !$omp task affinity(iterator(i=1:m): &
+  !$omp& x%a(1:2+0*i), x%a(i/d:i/d+1))
+  !$omp end task
+end
+! CHECK-LABEL: func.func @_QPaffinity_section(
+! CHECK: %[[BASE:.*]]:2 = hlfir.declare %arg0
+! CHECK-NOT: arith.divsi
+! CHECK: %[[FOLDED:.*]] = omp.iterator(
+! CHECK: %[[ADDR:.*]] = hlfir.designate %[[BASE]]#0{"a"}
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: %[[ENTRY:.*]] = omp.affinity_entry %[[PTR]],
+! CHECK: omp.yield(%[[ENTRY]] :
+! CHECK: %[[LIVE:.*]] = omp.iterator(
+! CHECK: arith.divsi
+! CHECK: %[[BOX:.*]] = hlfir.designate %[[BASE]]#0{"a"}
+! CHECK: %[[ADDR:.*]] = fir.box_addr %[[BOX]]
+! CHECK: %[[ELEMS:.*]] = fir.convert %{{.*}} : (index) -> i64
+! CHECK: %[[LEN:.*]] = arith.muli %[[ELEMS]], %{{.*}} : i64
+! CHECK: %[[PTR:.*]] = fir.convert %[[ADDR]]
+! CHECK: %[[ENTRY:.*]] = omp.affinity_entry %[[PTR]], %[[LEN]]
+! CHECK: omp.yield(%[[ENTRY]] :
+! CHECK: omp.task affinity(
+! CHECK-SAME: %[[FOLDED]] :
+! CHECK-SAME: %[[LIVE]] :
+
+! Scalar components occupy one element; component sections span two.
+! LLVM-LABEL: define {{.*}} @affinity_component_(
+! LLVM: store i64 4,
+! LLVM: store i64 4,
+! LLVM: call i32 @__kmpc_omp_reg_task_with_affinity(
+! LLVM-LABEL: define {{.*}} @affinity_section_(
+! LLVM: store i64 8,
+! LLVM: call i32 @__kmpc_omp_reg_task_with_affinity(
+
+! Empty ranges must suppress component and vector designator evaluation.
+
+subroutine depend_component_empty(a, m, d)
+  type t
+    integer :: field
+  end type
+  type(t) :: a(8)
+  integer :: m, d
+  !$omp task depend(iterator(i=2:1), in: &
+  !$omp& a(1+0*i)%field, a(i/d)%field)
+  !$omp end task
+end
+! LLVM-LABEL: define {{.*}} @depend_component_empty_(
+! LLVM-NOT: sdiv
+! LLVM: call i32 @__kmpc_omp_task_with_deps(
+! LLVM-SAME: i32 0, ptr
+! LLVM-NOT: sdiv
+! LLVM: ret void
+
+subroutine depend_vector_empty(a, m, d)
+  integer :: a(8)
+  integer :: m, d
+  !$omp task depend(iterator(i=2:1), in: &
+  !$omp& a([1+0*i]), a([i/d]))
+  !$omp end task
+end
+! LLVM-LABEL: define {{.*}} @depend_vector_empty_(
+! LLVM-NOT: sdiv
+! LLVM: call i32 @__kmpc_omp_task_with_deps(
+! LLVM-SAME: i32 0, ptr
+! LLVM-NOT: sdiv
+! LLVM: ret void
+
+subroutine depend_section_empty(x, m, d)
+  type t
+    integer :: a(8)
+  end type
+  type(t) :: x
+  integer :: m, d
+  !$omp task depend(iterator(i=2:1), in: &
+  !$omp& x%a(1:2+0*i), x%a(i/d:i/d+1))
+  !$omp end task
+end
+! LLVM-LABEL: define {{.*}} @depend_section_empty_(
+! LLVM-NOT: sdiv
+! LLVM: call i32 @__kmpc_omp_task_with_deps(
+! LLVM-SAME: i32 0, ptr
+! LLVM-NOT: sdiv
+! LLVM: ret void
+
+subroutine affinity_component_empty(a, m, d)
+  type t
+    integer :: field
+  end type
+  type(t) :: a(8)
+  integer :: m, d
+  !$omp task affinity(iterator(i=2:1): &
+  !$omp& a(1+0*i)%field, a(i/d)%field)
+  !$omp end task
+end
+! LLVM-LABEL: define {{.*}} @affinity_component_empty_(
+! LLVM-NOT: sdiv
+! LLVM: call i32 @__kmpc_omp_reg_task_with_affinity(
+! LLVM-SAME: i32 0, ptr
+! LLVM-NOT: sdiv
+! LLVM: ret void
+
+subroutine affinity_section_empty(x, m, d)
+  type t
+    integer :: a(8)
+  end type
+  type(t) :: x
+  integer :: m, d
+  !$omp task affinity(iterator(i=2:1): &
+  !$omp& x%a(1:2+0*i), x%a(i/d:i/d+1))
+  !$omp end task
+end
+! LLVM-LABEL: define {{.*}} @affinity_section_empty_(
+! LLVM-NOT: sdiv
+! LLVM: call i32 @__kmpc_omp_reg_task_with_affinity(
+! LLVM-SAME: i32 0, ptr
+! LLVM-NOT: sdiv
+! LLVM: ret void
diff --git a/flang/test/Lower/OpenMP/iterator-source-occurrences.f90 b/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
index 7387a544950663..4c89d5c827538c 100644
--- a/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
+++ b/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
@@ -14,15 +14,45 @@ subroutine depend_folded(a, m, d, i)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPdepend_folded(
-! CHECK: omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK: %[[A:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFdepend_foldedEa")
+! CHECK: %[[M:.*]]:2 = hlfir.declare {{.*}}uniq_name("{{.*}}Em")
+! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
+! CHECK: %[[MVAL:.*]] = fir.load %[[M]]#0
+! CHECK: %[[ILB:.*]] = fir.convert %[[ONE]] : (i32) -> index
+! CHECK: %[[IUB:.*]] = fir.convert %[[MVAL]] : (i32) -> index
+! CHECK: %[[ISTEP:.*]] = arith.constant 1 : index
+! CHECK: %[[JONE:.*]] = arith.constant 1 : i32
+! CHECK: %[[TWO:.*]] = arith.constant 2 : i32
+! CHECK: %[[JLB:.*]] = fir.convert %[[JONE]] : (i32) -> index
+! CHECK: %[[JUB:.*]] = fir.convert %[[TWO]] : (i32) -> index
+! CHECK: %[[JSTEP:.*]] = arith.constant 1 : index
+! CHECK: %[[IT_IJ:.*]] = omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]],
+! CHECK-SAME: %[[JLB]] to %[[JUB]] step %[[JSTEP]])
 ! CHECK: arith.divsi
 ! CHECK: omp.yield
-! CHECK: omp.iterator(%{{[^,:]+}}: index) =
-! CHECK: omp.yield
-! CHECK: omp.iterator(%{{[^,:]+}}: index) =
-! CHECK: omp.yield
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[I:.*]]: index) =
+! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]])
+! CHECK: %[[FIRST:.*]] = arith.constant 1 : index
+! CHECK: %[[FIXED:.*]] = hlfir.designate %[[A]]#0 (%[[FIRST]])
+! CHECK: %[[FIXED_PTR:.*]] = fir.convert %[[FIXED]]
+! CHECK: omp.yield(%[[FIXED_PTR]] : !llvm.ptr)
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[J:.*]]: index) =
+! CHECK-SAME: (%[[JLB]] to %[[JUB]] step %[[JSTEP]])
+! CHECK: %[[JVAL:.*]] = fir.convert %[[J]] : (index) -> i32
+! CHECK: fir.store %[[JVAL]] to %[[JMEM:.*]] : !fir.ref<i32>
+! CHECK: %[[JDECL:.*]]:2 = hlfir.declare %[[JMEM]]
+! CHECK: %[[JLOAD:.*]] = fir.load %[[JDECL]]#0
+! CHECK: %[[JIDX:.*]] = fir.convert %[[JLOAD]] : (i32) -> i64
+! CHECK: %[[VARIABLE:.*]] = hlfir.designate %[[A]]#0 (%[[JIDX]])
+! CHECK: %[[VARIABLE_PTR:.*]] = fir.convert %[[VARIABLE]]
+! CHECK: omp.yield(%[[VARIABLE_PTR]] : !llvm.ptr)
 ! CHECK-NOT: omp.iterator
-! CHECK: omp.task
+! CHECK: omp.task depend(
+! CHECK-SAME: %[[IT_IJ]] :
+! CHECK-SAME: %[[IT_I]] :
+! CHECK-SAME: %[[IT_J]] :
 ! CHECK: return
 
 ! The host i in the second clause must not be confused with iterator j.
@@ -48,15 +78,47 @@ subroutine affinity_folded(a, m, d, i)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPaffinity_folded(
-! CHECK: omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK: %[[A:.*]]:2 = hlfir.declare
+! CHECK-SAME: uniq_name("_QFaffinity_foldedEa")
+! CHECK: %[[M:.*]]:2 = hlfir.declare {{.*}}uniq_name("{{.*}}Em")
+! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
+! CHECK: %[[MVAL:.*]] = fir.load %[[M]]#0
+! CHECK: %[[ILB:.*]] = fir.convert %[[ONE]] : (i32) -> index
+! CHECK: %[[IUB:.*]] = fir.convert %[[MVAL]] : (i32) -> index
+! CHECK: %[[ISTEP:.*]] = arith.constant 1 : index
+! CHECK: %[[JONE:.*]] = arith.constant 1 : i32
+! CHECK: %[[TWO:.*]] = arith.constant 2 : i32
+! CHECK: %[[JLB:.*]] = fir.convert %[[JONE]] : (i32) -> index
+! CHECK: %[[JUB:.*]] = fir.convert %[[TWO]] : (i32) -> index
+! CHECK: %[[JSTEP:.*]] = arith.constant 1 : index
+! CHECK: %[[IT_IJ:.*]] = omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]],
+! CHECK-SAME: %[[JLB]] to %[[JUB]] step %[[JSTEP]])
 ! CHECK: arith.divsi
 ! CHECK: omp.yield
-! CHECK: omp.iterator(%{{[^,:]+}}: index) =
-! CHECK: omp.yield
-! CHECK: omp.iterator(%{{[^,:]+}}: index) =
-! CHECK: omp.yield
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[I:.*]]: index) =
+! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]])
+! CHECK: %[[FIRST:.*]] = arith.constant 1 : index
+! CHECK: %[[FIXED:.*]] = hlfir.designate %[[A]]#0 (%[[FIRST]])
+! CHECK: %[[FIXED_PTR:.*]] = fir.convert %[[FIXED]]
+! CHECK: %[[FIXED_ENTRY:.*]] = omp.affinity_entry %[[FIXED_PTR]],
+! CHECK: omp.yield(%[[FIXED_ENTRY]] :
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[J:.*]]: index) =
+! CHECK-SAME: (%[[JLB]] to %[[JUB]] step %[[JSTEP]])
+! CHECK: %[[JVAL:.*]] = fir.convert %[[J]] : (index) -> i32
+! CHECK: fir.store %[[JVAL]] to %[[JMEM:.*]] : !fir.ref<i32>
+! CHECK: %[[JDECL:.*]]:2 = hlfir.declare %[[JMEM]]
+! CHECK: %[[JLOAD:.*]] = fir.load %[[JDECL]]#0
+! CHECK: %[[JIDX:.*]] = fir.convert %[[JLOAD]] : (i32) -> i64
+! CHECK: %[[VARIABLE:.*]] = hlfir.designate %[[A]]#0 (%[[JIDX]])
+! CHECK: %[[VARIABLE_PTR:.*]] = fir.convert %[[VARIABLE]]
+! CHECK: %[[VARIABLE_ENTRY:.*]] = omp.affinity_entry %[[VARIABLE_PTR]],
+! CHECK: omp.yield(%[[VARIABLE_ENTRY]] :
 ! CHECK-NOT: omp.iterator
-! CHECK: omp.task
+! CHECK: omp.task affinity(
+! CHECK-SAME: %[[IT_IJ]] :
+! CHECK-SAME: %[[IT_I]] :
+! CHECK-SAME: %[[IT_J]] :
 ! CHECK: return
 
 ! The host i in the second task must not be confused with iterator j.
diff --git a/flang/test/Lower/OpenMP/iterator-target-data.f90 b/flang/test/Lower/OpenMP/iterator-target-data.f90
new file mode 100644
index 00000000000000..59141b13d92213
--- /dev/null
+++ b/flang/test/Lower/OpenMP/iterator-target-data.f90
@@ -0,0 +1,66 @@
+! RUN: split-file %s %t
+! RUN: not %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 \
+! RUN:   -fopenmp-targets=amdgcn-amd-amdhsa -o - %t/enter-folded.f90 \
+! RUN:   2>&1 | FileCheck %s --check-prefix=ENTER
+! RUN: not %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 \
+! RUN:   -fopenmp-targets=amdgcn-amd-amdhsa -o - %t/enter-live.f90 \
+! RUN:   2>&1 | FileCheck %s --check-prefix=ENTER
+! RUN: not %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 \
+! RUN:   -fopenmp-targets=amdgcn-amd-amdhsa -o - %t/exit-folded.f90 \
+! RUN:   2>&1 | FileCheck %s --check-prefix=EXIT
+! RUN: not %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 \
+! RUN:   -fopenmp-targets=amdgcn-amd-amdhsa -o - %t/exit-live.f90 \
+! RUN:   2>&1 | FileCheck %s --check-prefix=EXIT
+! RUN: not %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 \
+! RUN:   -fopenmp-targets=amdgcn-amd-amdhsa -o - %t/update-folded.f90 \
+! RUN:   2>&1 | FileCheck %s --check-prefix=UPDATE
+! RUN: not %flang_fc1 -emit-llvm -O1 -fopenmp -fopenmp-version=52 \
+! RUN:   -fopenmp-targets=amdgcn-amd-amdhsa -o - %t/update-live.f90 \
+! RUN:   2>&1 | FileCheck %s --check-prefix=UPDATE
+
+! Valid HLFIR dependences must be rejected at the translation boundary.
+! ENTER: Unhandled clause depend in omp.target_enter_data operation
+! EXIT: Unhandled clause depend in omp.target_exit_data operation
+! UPDATE: Unhandled clause depend in omp.target_update operation
+
+!--- enter-folded.f90
+subroutine s(a)
+  integer :: a(2)
+  !$omp target enter data map(to:a) &
+  !$omp& depend(iterator(i=1:1), in:a(1+0*i))
+end
+
+!--- enter-live.f90
+subroutine s(a)
+  integer :: a(2)
+  !$omp target enter data map(to:a) &
+  !$omp& depend(iterator(i=1:1), in:a(i))
+end
+
+!--- exit-folded.f90
+subroutine s(a)
+  integer :: a(2)
+  !$omp target exit data map(from:a) &
+  !$omp& depend(iterator(i=1:1), in:a(1+0*i))
+end
+
+!--- exit-live.f90
+subroutine s(a)
+  integer :: a(2)
+  !$omp target exit data map(from:a) &
+  !$omp& depend(iterator(i=1:1), in:a(i))
+end
+
+!--- update-folded.f90
+subroutine s(a)
+  integer :: a(2)
+  !$omp target update to(a) &
+  !$omp& depend(iterator(i=1:1), in:a(1+0*i))
+end
+
+!--- update-live.f90
+subroutine s(a)
+  integer :: a(2)
+  !$omp target update to(a) &
+  !$omp& depend(iterator(i=1:1), in:a(i))
+end
diff --git a/flang/test/Lower/OpenMP/task-affinity.f90 b/flang/test/Lower/OpenMP/task-affinity.f90
index 17e26454add658..813fb6f23251f6 100644
--- a/flang/test/Lower/OpenMP/task-affinity.f90
+++ b/flang/test/Lower/OpenMP/task-affinity.f90
@@ -19,14 +19,7 @@ end subroutine omp_task_affinity_elem
 ! CHECK: omp.parallel {
 ! CHECK:   %[[C1:.*]] = arith.constant 1 : index
 ! CHECK:   %[[ELEM:.*]] = hlfir.designate %[[A]]#0 (%[[C1]]) : (!fir.ref<!fir.array<100xi32>>, index) -> !fir.ref<i32>
-! CHECK:   %[[C0:.*]] = arith.constant 0 : index
-! CHECK:   %[[C4:.*]] = arith.constant 4 : i64
-! CHECK:   %[[ONE:.*]] = arith.constant 1 : index
-! CHECK:   %[[SUB:.*]] = arith.subi %[[C0]], %[[C0]] : index
-! CHECK:   %[[MUL:.*]] = arith.muli %[[SUB]], %[[ONE]] : index
-! CHECK:   %[[ADD:.*]] = arith.addi %[[ONE]], %[[MUL]] : index
-! CHECK:   %[[CAST:.*]] = fir.convert %[[ADD]] : (index) -> i64
-! CHECK:   %[[LEN:.*]] = arith.muli %[[CAST]], %[[C4]] : i64
+! CHECK:   %[[LEN:.*]] = arith.constant 4 : i64
 ! CHECK:   %[[ADDRI8:.*]] = fir.convert %[[ELEM]] : (!fir.ref<i32>) -> !fir.ref<i8>
 ! CHECK:   %[[ENTRY:.*]] = omp.affinity_entry %[[ADDRI8]], %[[LEN]] : (!fir.ref<i8>, i64) -> !omp.affinity_entry_ty<!fir.ref<i8>, i64>
 ! CHECK:   omp.task affinity(%[[ENTRY]] : !omp.affinity_entry_ty<!fir.ref<i8>, i64>) {
@@ -292,7 +285,7 @@ subroutine affinity_unused_iterator(m)
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
-! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[COOR_I:.*]] = hlfir.designate %[[A]]#0 (%[[IDX_I]])
 ! CHECK: %[[SIZE_I:.*]] = arith.constant 4 : i64
 ! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
 ! CHECK-SAME: (!fir.ref<i32>) -> !fir.ref<i8>
@@ -339,7 +332,7 @@ subroutine affinity_per_locator(m)
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
-! CHECK: %[[COOR_I:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX_I]]
+! CHECK: %[[COOR_I:.*]] = hlfir.designate %[[A]]#0 (%[[IDX_I]])
 ! CHECK: %[[SIZE_I:.*]] = arith.constant 4 : i64
 ! CHECK: %[[PTR_I:.*]] = fir.convert %[[COOR_I]]
 ! CHECK-SAME: (!fir.ref<i32>) -> !fir.ref<i8>
@@ -354,7 +347,7 @@ subroutine affinity_per_locator(m)
 ! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[MEM_J]]
 ! CHECK: %[[LD_J:.*]] = fir.load %[[DECL_J]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_J:.*]] = fir.convert %[[LD_J]] : (i32) -> i64
-! CHECK: %[[COOR_J:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %[[IDX_J]]
+! CHECK: %[[COOR_J:.*]] = hlfir.designate %[[B]]#0 (%[[IDX_J]])
 ! CHECK: %[[SIZE_J:.*]] = arith.constant 4 : i64
 ! CHECK: %[[PTR_J:.*]] = fir.convert %[[COOR_J]]
 ! CHECK-SAME: (!fir.ref<i32>) -> !fir.ref<i8>
@@ -395,8 +388,7 @@ subroutine task_affinity_iterator_simple()
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]] uniq_name("_QQ{{.*}}.omp.iter")
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR:.*]] = fir.array_coor {{.*}}(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate {{.*}} (%[[IV_I64]])
 ! CHECK:   %[[C4:.*]] = arith.constant 4 : i64
 ! CHECK:   %[[ADDRI8:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !fir.ref<i8>
 ! CHECK:   %[[ENTRY:.*]] = omp.affinity_entry %[[ADDRI8]], %[[C4]] : (!fir.ref<i8>, i64) -> !omp.affinity_entry_ty<!fir.ref<i8>, i64>
@@ -426,8 +418,7 @@ subroutine task_affinity_iterator_nondefault_lb()
 ! CHECK:   %[[IV_NDLB_DECL:.*]]:2 = hlfir.declare %[[IV_NDLB_MEM]]
 ! CHECK:   %[[IV_NDLB_LD:.*]] = fir.load %[[IV_NDLB_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_NDLB_I64:.*]] = fir.convert %[[IV_NDLB_LD]] : (i32) -> i64
-! CHECK:   %[[SHIFT_NDLB:.*]] = fir.shape_shift %c0, %c9 : (index, index) -> !fir.shapeshift<1>
-! CHECK:   %[[COOR_NDLB:.*]] = fir.array_coor {{.*}}(%[[SHIFT_NDLB]]) %[[IV_NDLB_I64]] : (!fir.box<!fir.array<9xi32>>, !fir.shapeshift<1>, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR_NDLB:.*]] = hlfir.designate {{.*}} (%[[IV_NDLB_I64]])
 ! CHECK:   %[[ELEM_NDLB:.*]] = fir.box_elesize %{{.*}} : (!fir.box<!fir.array<9xi32>>) -> index
 ! CHECK:   %[[ELEM_NDLB_I64:.*]] = fir.convert %[[ELEM_NDLB]] : (index) -> i64
 ! CHECK:   %[[ADDRI8_NDLB:.*]] = fir.convert %[[COOR_NDLB]] : (!fir.ref<i32>) -> !fir.ref<i8>
@@ -463,8 +454,8 @@ subroutine task_affinity_iterator_nondefault_lb_2d()
 ! CHECK:   %[[IV0_NDLB2_I64:.*]] = fir.convert %[[IV0_NDLB2_LD]] : (i32) -> i64
 ! CHECK:   %[[IV1_NDLB2_LD:.*]] = fir.load %[[IV1_NDLB2_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV1_NDLB2_I64:.*]] = fir.convert %[[IV1_NDLB2_LD]] : (i32) -> i64
-! CHECK:   %[[SHIFT_NDLB2:.*]] = fir.shape_shift %c0, %c5, %c-1, %c8 : (index, index, index, index) -> !fir.shapeshift<2>
-! CHECK:   %[[COOR_NDLB2:.*]] = fir.array_coor {{.*}}(%[[SHIFT_NDLB2]]) %[[IV0_NDLB2_I64]], %[[IV1_NDLB2_I64]] : (!fir.box<!fir.array<5x8xi32>>, !fir.shapeshift<2>, i64, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR_NDLB2:.*]] = hlfir.designate
+! CHECK-SAME: {{.*}} (%[[IV0_NDLB2_I64]], %[[IV1_NDLB2_I64]])
 ! CHECK:   %[[ELEM_NDLB2:.*]] = fir.box_elesize %{{.*}} : (!fir.box<!fir.array<5x8xi32>>) -> index
 ! CHECK:   %[[ELEM_NDLB2_I64:.*]] = fir.convert %[[ELEM_NDLB2]] : (index) -> i64
 ! CHECK:   %[[ADDRI8_NDLB2:.*]] = fir.convert %[[COOR_NDLB2]] : (!fir.ref<i32>) -> !fir.ref<i8>
@@ -503,8 +494,7 @@ subroutine task_affinity_iterator_multi_dimension()
 ! CHECK:   %[[IV0_I64:.*]] = fir.convert %[[IV0_LD]] : (i32) -> i64
 ! CHECK:   %[[IV1_LD:.*]] = fir.load %[[IV1_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV1_I64:.*]] = fir.convert %[[IV1_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c4, %c6 : (index, index) -> !fir.shape<2>
-! CHECK:   %[[COOR:.*]] = fir.array_coor {{.*}}(%[[SHAPE]]) %[[IV0_I64]], %[[IV1_I64]] : (!fir.ref<!fir.array<4x6xi32>>, !fir.shape<2>, i64, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate {{.*}} (%[[IV0_I64]], %[[IV1_I64]])
 ! CHECK:   %[[C4:.*]] = arith.constant 4 : i64
 ! CHECK:   %[[ADDRI8:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !fir.ref<i8>
 ! CHECK:   %[[ENTRY:.*]] = omp.affinity_entry %[[ADDRI8]], %[[C4]] : (!fir.ref<i8>, i64) -> !omp.affinity_entry_ty<!fir.ref<i8>, i64>
@@ -538,8 +528,8 @@ subroutine task_affinity_iterator_reordered()
 ! CHECK:   %[[RO_IV1_I64:.*]] = fir.convert %[[RO_IV1_LD]] : (i32) -> i64
 ! CHECK:   %[[RO_IV0_LD:.*]] = fir.load %[[RO_IV0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[RO_IV0_I64:.*]] = fir.convert %[[RO_IV0_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE:.*]] = fir.shape %c4, %c6 : (index, index) -> !fir.shape<2>
-! CHECK:   %[[COOR:.*]] = fir.array_coor {{.*}}(%[[SHAPE]]) %[[RO_IV1_I64]], %[[RO_IV0_I64]] : (!fir.ref<!fir.array<4x6xi32>>, !fir.shape<2>, i64, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR:.*]] = hlfir.designate
+! CHECK-SAME: {{.*}} (%[[RO_IV1_I64]], %[[RO_IV0_I64]])
 
 subroutine task_affinity_iterator_expr_subscript()
   integer, parameter :: n = 5, m = 6
@@ -565,12 +555,12 @@ subroutine task_affinity_iterator_expr_subscript()
 ! CHECK:   %[[IVB_DECL:.*]]:2 = hlfir.declare %[[IVB_MEM]]
 ! CHECK:   %[[IVA_LD:.*]] = fir.load %[[IVA_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C1_I32:.*]] = arith.constant 1 : i32
-! CHECK:   %[[IP1_I32:.*]] = arith.addi %[[IVA_LD]], %[[C1_I32]] : i32
+! CHECK:   %[[IP1_I32:.*]] = arith.addi %[[IVA_LD]], %[[C1_I32]]
+! CHECK-SAME: overflow<nsw> : i32
 ! CHECK:   %[[IP1_I64:.*]] = fir.convert %[[IP1_I32]] : (i32) -> i64
 ! CHECK:   %[[IVB_LD:.*]] = fir.load %[[IVB_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IVB_I64:.*]] = fir.convert %[[IVB_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE2:.*]] = fir.shape %c5, %c6 : (index, index) -> !fir.shape<2>
-! CHECK:   %[[COOR2:.*]] = fir.array_coor {{.*}}(%[[SHAPE2]]) %[[IP1_I64]], %[[IVB_I64]] : (!fir.ref<!fir.array<5x6xi32>>, !fir.shape<2>, i64, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR2:.*]] = hlfir.designate {{.*}} (%[[IP1_I64]], %[[IVB_I64]])
 
 subroutine task_affinity_iterator_section_subscript()
   integer, parameter :: n = 5, m = 6
@@ -596,12 +586,19 @@ subroutine task_affinity_iterator_section_subscript()
 ! CHECK:   %[[IVS1_DECL:.*]]:2 = hlfir.declare %[[IVS1_MEM]]
 ! CHECK:   %[[IVS0_LD:.*]] = fir.load %[[IVS0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IVS0_I64:.*]] = fir.convert %[[IVS0_LD]] : (i32) -> i64
+! CHECK:   %[[LOWER:.*]] = fir.convert %[[IVS0_I64]] : (i64) -> index
 ! CHECK:   %[[IVS1_LD:.*]] = fir.load %[[IVS1_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C2_I32:.*]] = arith.constant 2 : i32
-! CHECK:   %[[JP2_I32:.*]] = arith.addi %[[IVS1_LD]], %[[C2_I32]] : i32
+! CHECK:   %[[JP2_I32:.*]] = arith.addi %[[IVS1_LD]], %[[C2_I32]]
+! CHECK-SAME: overflow<nsw> : i32
 ! CHECK:   %[[JP2_I64:.*]] = fir.convert %[[JP2_I32]] : (i32) -> i64
-! CHECK:   %[[SHAPE3:.*]] = fir.shape %c5, %c6 : (index, index) -> !fir.shape<2>
-! CHECK:   %[[COOR3:.*]] = fir.array_coor {{.*}}(%[[SHAPE3]]) %[[IVS0_I64]], %[[JP2_I64]] : (!fir.ref<!fir.array<5x6xi32>>, !fir.shape<2>, i64, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR3:.*]] = hlfir.designate
+! CHECK-SAME: (%[[LOWER]]:{{.*}}, %[[JP2_I64]])
+! CHECK:   %[[ADDR3:.*]] = fir.box_addr %[[COOR3]]
+! CHECK:   %[[ELEMS3:.*]] = fir.convert %{{.*}} : (index) -> i64
+! CHECK:   %[[LEN3:.*]] = arith.muli %[[ELEMS3]], %{{.*}} : i64
+! CHECK:   %[[PTR3:.*]] = fir.convert %[[ADDR3]]
+! CHECK:   omp.affinity_entry %[[PTR3]], %[[LEN3]]
 
 subroutine task_affinity_iterator_section_implicit_lower()
   integer, parameter :: n = 5, m = 6
@@ -625,10 +622,11 @@ subroutine task_affinity_iterator_section_implicit_lower()
 ! CHECK:   %[[C1_IDX:.*]] = arith.constant 1 : index
 ! CHECK:   %[[IVT1_LD:.*]] = fir.load %[[IVT1_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C2_I32_2:.*]] = arith.constant 2 : i32
-! CHECK:   %[[JP2_I32_2:.*]] = arith.addi %[[IVT1_LD]], %[[C2_I32_2]] : i32
+! CHECK:   %[[JP2_I32_2:.*]] = arith.addi %[[IVT1_LD]], %[[C2_I32_2]]
+! CHECK-SAME: overflow<nsw> : i32
 ! CHECK:   %[[JP2_I64_2:.*]] = fir.convert %[[JP2_I32_2]] : (i32) -> i64
-! CHECK:   %[[SHAPE4:.*]] = fir.shape %c5, %c6 : (index, index) -> !fir.shape<2>
-! CHECK:   %[[COOR4:.*]] = fir.array_coor {{.*}}(%[[SHAPE4]]) %[[C1_IDX]], %[[JP2_I64_2]] : (!fir.ref<!fir.array<5x6xi32>>, !fir.shape<2>, index, i64) -> !fir.ref<i32>
+! CHECK:   %[[COOR4:.*]] = hlfir.designate
+! CHECK-SAME: (%[[C1_IDX]]:{{.*}}, %[[JP2_I64_2]])
 
 subroutine task_affinity_iterator_char_simple()
   integer, parameter :: n = 8
@@ -651,8 +649,7 @@ subroutine task_affinity_iterator_char_simple()
 ! CHECK:   %[[IVC_DECL:.*]]:2 = hlfir.declare %[[IVC_MEM]]
 ! CHECK:   %[[IVC_LD:.*]] = fir.load %[[IVC_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IVC_I64:.*]] = fir.convert %[[IVC_LD]] : (i32) -> i64
-! CHECK:   %[[SHAPE5:.*]] = fir.shape {{.*}} : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR5:.*]] = fir.array_coor {{.*}}(%[[SHAPE5]]) %[[IVC_I64]] : ({{.*}}, !fir.shape<1>, i64) -> !fir.ref<!fir.char<1,7>>
+! CHECK:   %[[COOR5:.*]] = hlfir.designate {{.*}} (%[[IVC_I64]])
 ! CHECK:   %[[C1_I64:.*]] = arith.constant 1 : i64
 ! CHECK:   %[[C7_I64:.*]] = fir.convert %c7 : (index) -> i64
 ! CHECK:   %[[ELEM5:.*]] = arith.muli %[[C7_I64]], %[[C1_I64]] : i64
@@ -680,10 +677,10 @@ subroutine task_affinity_iterator_char_expr_subscript()
 ! CHECK:   %[[IVC2_DECL:.*]]:2 = hlfir.declare %[[IVC2_MEM]]
 ! CHECK:   %[[IVC2_LD:.*]] = fir.load %[[IVC2_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C1_I32_6:.*]] = arith.constant 1 : i32
-! CHECK:   %[[IP1C_I32:.*]] = arith.addi %[[IVC2_LD]], %[[C1_I32_6]] : i32
+! CHECK:   %[[IP1C_I32:.*]] = arith.addi %[[IVC2_LD]], %[[C1_I32_6]]
+! CHECK-SAME: overflow<nsw> : i32
 ! CHECK:   %[[IP1C_I64:.*]] = fir.convert %[[IP1C_I32]] : (i32) -> i64
-! CHECK:   %[[SHAPE6:.*]] = fir.shape {{.*}} : (index) -> !fir.shape<1>
-! CHECK:   %[[COOR6:.*]] = fir.array_coor {{.*}}(%[[SHAPE6]]) %[[IP1C_I64]] : ({{.*}}, !fir.shape<1>, i64) -> !fir.ref<!fir.char<1,7>>
+! CHECK:   %[[COOR6:.*]] = hlfir.designate {{.*}} (%[[IP1C_I64]])
 ! CHECK:   %[[C1_I64_2:.*]] = arith.constant 1 : i64
 ! CHECK:   %[[C7_I64_2:.*]] = fir.convert %c7 : (index) -> i64
 ! CHECK:   %[[ELEM6:.*]] = arith.muli %[[C7_I64_2]], %[[C1_I64_2]] : i64
@@ -707,8 +704,10 @@ subroutine task_affinity_iterator_char_runtime(n, l)
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_char_runtime(
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) typeparams %{{.*}} uniq_name("_QFtask_affinity_iterator_char_runtimeEa")
 ! CHECK: %[[ITER:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[COOR:.*]] = fir.array_coor %[[A]]#0({{.*}}) {{.*}} : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, i64) -> !fir.ref<!fir.char<1,?>>
+! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 ({{.*}})
+! CHECK:   %[[RAW:.*]]:2 = fir.unboxchar %[[COOR]]
 ! CHECK:   %[[ELEM:.*]] = fir.box_elesize %[[A]]#0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index
 ! CHECK:   %[[ELEM_I64:.*]] = fir.convert %[[ELEM]] : (index) -> i64
-! CHECK:   %[[ADDR:.*]] = fir.convert %[[COOR]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
+! CHECK:   %[[ADDR:.*]] = fir.convert %[[RAW]]#0
+! CHECK-SAME: : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
 ! CHECK:   %[[ENTRY:.*]] = omp.affinity_entry %[[ADDR]], %[[ELEM_I64]] : (!fir.ref<i8>, i64) -> !omp.affinity_entry_ty<!fir.ref<i8>, i64>
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 231aab0d904442..d6a78444cac428 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -416,7 +416,8 @@ static LogicalResult checkImplementationStatus(Operation &op) {
       result = todo("ompx_bare");
   };
   auto checkDepend = [&todo](auto op, LogicalResult &result) {
-    if (!op.getDependVars().empty() || op.getDependKinds())
+    if (!op.getDependVars().empty() || op.getDependKinds() ||
+        !op.getDependIterated().empty() || op.getDependIteratedKinds())
       result = todo("depend");
   };
   auto checkHint = [](auto op, LogicalResult &) {
diff --git a/mlir/test/Target/LLVMIR/openmp-iterator-wide.mlir b/mlir/test/Target/LLVMIR/openmp-iterator-wide.mlir
index 93791a3bbf0f53..66560e6454ff9b 100644
--- a/mlir/test/Target/LLVMIR/openmp-iterator-wide.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-iterator-wide.mlir
@@ -1,6 +1,38 @@
 // RUN: mlir-translate --mlir-to-llvmir %s | FileCheck %s
 // RUN: mlir-translate --mlir-to-llvmir %s | opt -passes=verify -disable-output
 
+// Narrowing the lower bound to i64 would turn this empty range into 1:2.
+llvm.func @empty_positive(%x: !llvm.ptr) {
+  %lb = llvm.mlir.constant(18446744073709551617 : i128) : i128
+  %ub = llvm.mlir.constant(2 : i128) : i128
+  %st = llvm.mlir.constant(1 : i128) : i128
+  %it = omp.iterator(%i: i128) = (%lb to %ub step %st) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  omp.taskwait depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>)
+  llvm.return
+}
+// CHECK-LABEL: define void @empty_positive(
+// CHECK: icmp ult i64 %{{.*}}, 0
+// CHECK: call void @__kmpc_omp_taskwait_deps_51(
+// CHECK-SAME: i32 0, ptr %{{.*}}, i32 0, ptr null, i32 0)
+
+// The negative-step counterpart must also remain empty.
+llvm.func @empty_negative(%x: !llvm.ptr) {
+  %lb = llvm.mlir.constant(2 : i128) : i128
+  %ub = llvm.mlir.constant(18446744073709551617 : i128) : i128
+  %st = llvm.mlir.constant(-1 : i128) : i128
+  %it = omp.iterator(%i: i128) = (%lb to %ub step %st) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  omp.taskwait depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>)
+  llvm.return
+}
+// CHECK-LABEL: define void @empty_negative(
+// CHECK: icmp ult i64 %{{.*}}, 0
+// CHECK: call void @__kmpc_omp_taskwait_deps_51(
+// CHECK-SAME: i32 0, ptr %{{.*}}, i32 0, ptr null, i32 0)
+
 // Bounds and induction values keep their declared width; only the trip count
 // is converted to i64.
 llvm.func @dynamic(%x: !llvm.ptr, %lb: i128, %ub: i128, %st: i128) {
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 327d0915388636..2b502ac2ef0288 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -1,5 +1,52 @@
 // RUN: mlir-translate -mlir-to-llvmir -split-input-file -verify-diagnostics %s
 
+// -----
+
+llvm.func @target_enter_data_iterated_depend(%x: !llvm.ptr) {
+  %one = llvm.mlir.constant(1 : i64) : i64
+  %it = omp.iterator(%i: i64) = (%one to %one step %one) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  // expected-error at +2 {{Unhandled clause depend in omp.target_enter_data}}
+  // expected-error at +1 {{LLVM Translation failed}}
+  omp.target_enter_data depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>) {
+    omp.terminator
+  }
+  llvm.return
+}
+
+// -----
+
+llvm.func @target_exit_data_iterated_depend(%x: !llvm.ptr) {
+  %one = llvm.mlir.constant(1 : i64) : i64
+  %it = omp.iterator(%i: i64) = (%one to %one step %one) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  // expected-error at +2 {{Unhandled clause depend in omp.target_exit_data}}
+  // expected-error at +1 {{LLVM Translation failed}}
+  omp.target_exit_data depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>) {
+    omp.terminator
+  }
+  llvm.return
+}
+
+// -----
+
+llvm.func @target_update_iterated_depend(%x: !llvm.ptr) {
+  %one = llvm.mlir.constant(1 : i64) : i64
+  %it = omp.iterator(%i: i64) = (%one to %one step %one) {
+    omp.yield(%x : !llvm.ptr)
+  } -> !omp.iterated<!llvm.ptr>
+  // expected-error at +2 {{Unhandled clause depend in omp.target_update}}
+  // expected-error at +1 {{LLVM Translation failed}}
+  omp.target_update depend(taskdependin -> %it : !omp.iterated<!llvm.ptr>) {
+    omp.terminator
+  }
+  llvm.return
+}
+
+// -----
+
 
 llvm.func @atomic_hint(%v : !llvm.ptr, %x : !llvm.ptr, %expr : i32) {
   // expected-warning at below {{hint clause discarded}}

>From 14925006b832ec0584275f7a0613d9d9380575ad Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Tue, 6 Oct 2026 13:19:09 -0500
Subject: [PATCH 3/3] Lower iterator ranges in the iterator's own type

Flang converted iterator bounds and steps to index before building
omp.iterator. An integer(16) range such as
9223372036854775807:9223372036854775809 therefore wrapped and produced no
dependences or affinity entries.

Convert begin and end to the iterator variable's type, and build each
range in the wider of that type and the step's type so that a large step
can't change direction. Translation counts each range one bit wider than
its operands, so wide kinds keep all their entries.

Lowering now relies on the iterator being an integer, so DEPEND
iterators get the same semantic checks as the other clauses that take an
iterator modifier. The range warnings in those checks now skip constants
wider than 64 bits, which they used to truncate.
---
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |  38 ++--
 flang/lib/Semantics/check-omp-structure.cpp   |  18 +-
 flang/test/Lower/OpenMP/depend-iterator.f90   | 167 +++++++++---------
 .../Lower/OpenMP/iterator-empty-range.f90     |  84 ++++++---
 .../OpenMP/iterator-source-occurrences.f90    |  74 ++++----
 flang/test/Lower/OpenMP/task-affinity.f90     | 106 +++++------
 flang/test/Semantics/OpenMP/depend08.f90      |  17 ++
 7 files changed, 261 insertions(+), 243 deletions(-)
 create mode 100644 flang/test/Semantics/OpenMP/depend08.f90

diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index e99c803fff5d71..72f6e7e59def77 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -256,23 +256,23 @@ static IteratorRange lowerIteratorRange(
   mlir::Value ubVal =
       fir::getBase(converter.genExprValue(toEvExpr(ubExpr), stmtCtx));
 
-  auto toIndex = [](fir::FirOpBuilder &builder, mlir::Location loc,
-                    mlir::Value v) -> mlir::Value {
-    if (v.getType().isIndex())
-      return v;
-    return fir::ConvertOp::create(builder, loc, builder.getIndexType(), v);
-  };
-
-  r.lb = toIndex(builder, loc, lbVal);
-  r.ub = toIndex(builder, loc, ubVal);
-
-  if (stExpr) {
-    mlir::Value stVal =
-        fir::getBase(converter.genExprValue(toEvExpr(*stExpr), stmtCtx));
-    r.step = toIndex(builder, loc, stVal);
-  } else {
-    r.step = mlir::arith::ConstantIndexOp::create(builder, loc, 1);
-  }
+  // Begin and end take the iterator's type, but the step keeps its own. Count
+  // in the wider of the two so that neither is narrowed.
+  mlir::Type ivTy = converter.genType(*r.ivSym);
+  mlir::Value stVal =
+      stExpr ? fir::getBase(converter.genExprValue(toEvExpr(*stExpr), stmtCtx))
+             : builder.createIntegerConstant(loc, ivTy, 1);
+  mlir::Type rangeTy = ivTy;
+  if (auto stTy = mlir::dyn_cast<mlir::IntegerType>(stVal.getType()))
+    if (stTy.isSignless() &&
+        stTy.getWidth() > mlir::cast<mlir::IntegerType>(ivTy).getWidth())
+      rangeTy = stTy;
+
+  r.lb = builder.createConvert(loc, rangeTy,
+                               builder.createConvert(loc, ivTy, lbVal));
+  r.ub = builder.createConvert(loc, rangeTy,
+                               builder.createConvert(loc, ivTy, ubVal));
+  r.step = builder.createConvert(loc, rangeTy, stVal);
 
   return r;
 }
@@ -306,8 +306,8 @@ static mlir::Value buildIteratorOp(Fortran::lower::AbstractConverter &converter,
 
   llvm::SmallVector<mlir::Value> ivs;
   ivs.reserve(ranges.size());
-  for (size_t i = 0; i < ranges.size(); ++i)
-    ivs.push_back(body->addArgument(builder.getIndexType(), loc));
+  for (const IteratorRange &r : ranges)
+    ivs.push_back(body->addArgument(r.lb.getType(), loc));
 
   Fortran::lower::SymMap &symMap = converter.getSymbolMap();
   Fortran::lower::SymMapScope scope(symMap);
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6193b297b62fb5..5b7f2db27d1cca 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1569,15 +1569,24 @@ void OmpStructureChecker::CheckIteratorRange(
         "The begin and end expressions in iterator range-specification are "
         "mandatory"_err_en_US);
   }
+  // GetIntValue keeps only the low 64 bits, so skip wider constants.
+  auto getIntValue{[](const auto &e) -> std::optional<int64_t> {
+    if (const auto *expr{GetExpr(nullptr, e)}) {
+      if (auto type{expr->GetType()}; type && type->kind() <= 8) {
+        return evaluate::ToInt64(*expr);
+      }
+    }
+    return std::nullopt;
+  }};
   // [5.2:67:19] In a range-specification, if the step is not specified its
   // value is implicitly defined to be 1.
-  if (auto stepv{step ? GetIntValue(*step) : std::optional<int64_t>{1}}) {
+  if (auto stepv{step ? getIntValue(*step) : std::optional<int64_t>{1}}) {
     if (*stepv == 0) {
       context_.Say(
           x.source, "The step value in the iterator range is 0"_warn_en_US);
     } else if (begin && end) {
-      std::optional<int64_t> beginv{GetIntValue(*begin)};
-      std::optional<int64_t> endv{GetIntValue(*end)};
+      std::optional<int64_t> beginv{getIntValue(*begin)};
+      std::optional<int64_t> endv{getIntValue(*end)};
       if (beginv && endv) {
         if (*stepv > 0 && *beginv > *endv) {
           context_.Say(x.source,
@@ -5266,7 +5275,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
       }
     }
     auto &modifiers{OmpGetModifiers(*taskDep)};
-    if (OmpGetUniqueModifier<parser::OmpIterator>(modifiers)) {
+    if (auto *iter{OmpGetUniqueModifier<parser::OmpIterator>(modifiers)}) {
+      CheckIteratorModifier(*iter);
       if (dir == llvm::omp::OMPD_depobj) {
         context_.Say(GetContext().clauseSource,
             "An iterator-modifier may specify multiple locators, a DEPEND clause on a DEPOBJ construct must only specify one locator"_warn_en_US);
diff --git a/flang/test/Lower/OpenMP/depend-iterator.f90 b/flang/test/Lower/OpenMP/depend-iterator.f90
index bd83fdc8a01ad0..42d6a4f8d7688c 100644
--- a/flang/test/Lower/OpenMP/depend-iterator.f90
+++ b/flang/test/Lower/OpenMP/depend-iterator.f90
@@ -24,15 +24,12 @@ subroutine depend_unused_iterator(m)
 ! CHECK-SAME: uniq_name("_QFdepend_unused_iteratorEa")
 ! CHECK: %[[M:.*]]:2 = hlfir.declare
 ! CHECK-SAME: uniq_name("_QFdepend_unused_iteratorEm")
-! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
-! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
-! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
-! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
-! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
-! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK: %[[I_LB:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: i32) =
 ! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
-! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
-! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[IV_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
@@ -63,20 +60,15 @@ subroutine depend_per_locator(m)
 ! CHECK-SAME: uniq_name("_QFdepend_per_locatorEc")
 ! CHECK: %[[M:.*]]:2 = hlfir.declare
 ! CHECK-SAME: uniq_name("_QFdepend_per_locatorEm")
-! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
-! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
-! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
-! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
-! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
-! CHECK: %[[J_LB32:.*]] = arith.constant 3 : i32
-! CHECK: %[[J_UB32:.*]] = fir.load %[[M]]#0 : !fir.ref<i32>
-! CHECK: %[[J_LB:.*]] = fir.convert %[[J_LB32]] : (i32) -> index
-! CHECK: %[[J_UB:.*]] = fir.convert %[[J_UB32]] : (i32) -> index
-! CHECK: %[[J_STEP:.*]] = arith.constant 1 : index
-! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK: %[[I_LB:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[J_LB:.*]] = arith.constant 3 : i32
+! CHECK: %[[J_UB:.*]] = fir.load %[[M]]#0 : !fir.ref<i32>
+! CHECK: %[[J_STEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: i32) =
 ! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
-! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
-! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[IV_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
@@ -85,10 +77,9 @@ subroutine depend_per_locator(m)
 ! CHECK-SAME: (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK: omp.yield(%[[PTR_I]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
-! CHECK: %[[IT_J:.*]] = omp.iterator(%[[IV_J:.*]]: index) =
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[IV_J:.*]]: i32) =
 ! CHECK-SAME: (%[[J_LB]] to %[[J_UB]] step %[[J_STEP]]) {
-! CHECK: %[[V32_J:.*]] = fir.convert %[[IV_J]] : (index) -> i32
-! CHECK: fir.store %[[V32_J]] to %[[MEM_J:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[IV_J]] to %[[MEM_J:.*]] : !fir.ref<i32>
 ! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[MEM_J]]
 ! CHECK: %[[LD_J:.*]] = fir.load %[[DECL_J]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_J:.*]] = fir.convert %[[LD_J]] : (i32) -> i64
@@ -102,6 +93,28 @@ subroutine depend_per_locator(m)
 ! CHECK-SAME: taskdependin -> %[[IT_I]] : !omp.iterated<!llvm.ptr>,
 ! CHECK-SAME: taskdependin -> %[[IT_J]] : !omp.iterated<!llvm.ptr>) {
 
+! Each range and induction value keeps its own iterator's kind.
+subroutine depend_iterator_kinds(a, n)
+  integer :: a(4, 4)
+  integer(8) :: n
+  !$omp task depend(iterator(integer(8) :: i = 1:n, j = 1:2), in: a(i, j))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: func.func @_QPdepend_iterator_kinds(
+! CHECK: %[[N:.*]]:2 = hlfir.declare {{.*}}uniq_name("_QFdepend_iterator_kindsEn")
+! CHECK: %[[I_UB:.*]] = fir.load %[[N]]#0 : !fir.ref<i64>
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i64
+! CHECK: %[[I_LB:.*]] = fir.convert %{{.*}} : (i32) -> i64
+! CHECK: %[[J_LB:.*]] = arith.constant 1 : i32
+! CHECK: %[[J_UB:.*]] = arith.constant 2 : i32
+! CHECK: %[[J_STEP:.*]] = arith.constant 1 : i32
+! CHECK: omp.iterator(%[[IV_I:.*]]: i64, %[[IV_J:.*]]: i32) =
+! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]],
+! CHECK-SAME: %[[J_LB]] to %[[J_UB]] step %[[J_STEP]]) {
+! CHECK: fir.store %[[IV_I]] to %{{.*}} : !fir.ref<i64>
+! CHECK: fir.store %[[IV_J]] to %{{.*}} : !fir.ref<i32>
+
 subroutine task_depend_iterator_simple()
   integer, parameter :: n = 16
   integer :: a(n)
@@ -113,9 +126,8 @@ subroutine task_depend_iterator_simple()
 
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_simple()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_simpleEa")
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
-! CHECK:   fir.store %[[IV_I32]] to %[[IV_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV]] to %[[IV_MEM:.*]] : !fir.ref<i32>
 ! Iterator IV temp must be named in the compiler-generated namespace ("_QQ"
 ! prefix) so it is not emitted as a bogus user local in DWARF under -g.
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]] uniq_name("_QQ{{.*}}.omp.iter")
@@ -139,12 +151,10 @@ subroutine task_depend_iterator_2d()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_2d()
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
-! CHECK:   fir.store %[[IV0_I32]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: i32, %[[IV1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV0]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV0_DECL:.*]]:2 = hlfir.declare %[[IV0_MEM]]
-! CHECK:   %[[IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
-! CHECK:   fir.store %[[IV1_I32]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IV1]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV1_DECL:.*]]:2 = hlfir.declare %[[IV1_MEM]]
 ! CHECK:   %[[IV0_LD:.*]] = fir.load %[[IV0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV0_I64:.*]] = fir.convert %[[IV0_LD]] : (i32) -> i64
@@ -168,7 +178,7 @@ subroutine task_depend_iterator_mixed()
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_mixed()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_mixedEa")
 ! CHECK: %[[X:.*]]:2 = hlfir.declare %{{.*}} uniq_name("_QFtask_depend_iterator_mixedEx")
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: omp.task depend(taskdependout -> %[[X]]#0 : !fir.ref<i32>, taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
@@ -183,13 +193,10 @@ subroutine task_depend_iterator_step()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_step()
-! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
-! CHECK: %[[C16_I32:.*]] = arith.constant 16 : i32
-! CHECK: %[[LB:.*]] = fir.convert %[[C1_I32]] : (i32) -> index
-! CHECK: %[[UB:.*]] = fir.convert %[[C16_I32]] : (i32) -> index
-! CHECK: %[[C2_I32:.*]] = arith.constant 2 : i32
-! CHECK: %[[STEP:.*]] = fir.convert %[[C2_I32]] : (i32) -> index
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
+! CHECK: %[[LB:.*]] = arith.constant 1 : i32
+! CHECK: %[[UB:.*]] = arith.constant 16 : i32
+! CHECK: %[[STEP:.*]] = arith.constant 2 : i32
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: omp.task depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
@@ -206,12 +213,12 @@ subroutine task_depend_iterator_multi_obj()
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_multi_obj()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_multi_objEa")
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_multi_objEb")
-! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   %[[PTR1:.*]] = fir.convert %[[COOR1]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR1]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
-! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   %[[PTR2:.*]] = fir.convert %[[COOR2]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR2]] : !llvm.ptr)
@@ -232,12 +239,10 @@ subroutine task_depend_iterator_expr_subscript()
 
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_expr_subscript()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_expr_subscriptEa")
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
-! CHECK:   fir.store %[[IV0_I32]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: i32, %[[IV1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV0]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV0_DECL:.*]]:2 = hlfir.declare %[[IV0_MEM]]
-! CHECK:   %[[IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
-! CHECK:   fir.store %[[IV1_I32]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IV1]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV1_DECL:.*]]:2 = hlfir.declare %[[IV1_MEM]]
 ! CHECK:   %[[IV0_LD:.*]] = fir.load %[[IV0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C1_I32:.*]] = arith.constant 1 : i32
@@ -267,12 +272,12 @@ subroutine task_depend_multi_iter_clauses()
 ! CHECK-LABEL: func.func @_QPtask_depend_multi_iter_clauses()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_multi_iter_clausesEa")
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_multi_iter_clausesEb")
-! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   %[[PTR1:.*]] = fir.convert %[[COOR1]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR1]] : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
-! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   %[[PTR2:.*]] = fir.convert %[[COOR2]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR2]] : !llvm.ptr)
@@ -289,13 +294,10 @@ subroutine task_depend_iterator_negative_step()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_negative_step()
-! CHECK: %[[C16_I32:.*]] = arith.constant 16 : i32
-! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
-! CHECK: %[[LB:.*]] = fir.convert %[[C16_I32]] : (i32) -> index
-! CHECK: %[[UB:.*]] = fir.convert %[[C1_I32]] : (i32) -> index
-! CHECK: %[[CM1_I32:.*]] = arith.constant -1 : i32
-! CHECK: %[[STEP:.*]] = fir.convert %[[CM1_I32]] : (i32) -> index
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
+! CHECK: %[[LB:.*]] = arith.constant 16 : i32
+! CHECK: %[[UB:.*]] = arith.constant 1 : i32
+! CHECK: %[[STEP:.*]] = arith.constant -1 : i32
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
 ! CHECK: omp.task depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
@@ -315,7 +317,7 @@ subroutine task_depend_iterator_mixed_within_clause()
 ! CHECK-LABEL: func.func @_QPtask_depend_iterator_mixed_within_clause()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtask_depend_iterator_mixed_within_clauseEa")
 ! CHECK: %[[A1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})  : (!fir.ref<!fir.array<16xi32>>, index) -> !fir.ref<i32>
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
 ! CHECK:   omp.yield(%[[PTR]] : !llvm.ptr)
@@ -338,9 +340,8 @@ subroutine target_depend_iterator()
 
 ! CHECK-LABEL: func.func @_QPtarget_depend_iterator()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_depend_iteratorEa")
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
-! CHECK:   fir.store %[[IV_I32]] to %[[IV_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV]] to %[[IV_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
@@ -369,15 +370,15 @@ subroutine target_depend_iterator_multi()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_depend_iterator_multiEa")
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_depend_iterator_multiEb")
 ! CHECK: %[[C:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_depend_iterator_multiEc")
-! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
-! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
-! CHECK: %[[IT3:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT3:.*]] = omp.iterator(%{{.*}}: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR3:.*]] = hlfir.designate %[[C]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -400,9 +401,8 @@ subroutine target_enter_data_depend_iterator()
 
 ! CHECK-LABEL: func.func @_QPtarget_enter_data_depend_iterator()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_enter_data_depend_iteratorEa")
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
-! CHECK:   fir.store %[[IV_I32]] to %[[IV_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV]] to %[[IV_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
@@ -426,12 +426,10 @@ subroutine target_enter_data_depend_iterator_expr()
 ! CHECK-LABEL: func.func @_QPtarget_enter_data_depend_iterator_expr()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_enter_data_depend_iterator_exprEa")
 ! CHECK: %[[A1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})  : (!fir.ref<!fir.array<16xi32>>, index) -> !fir.ref<i32>
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
-! CHECK:   fir.store %[[IV0_I32]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: i32, %[[IV1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV0]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV0_DECL:.*]]:2 = hlfir.declare %[[IV0_MEM]]
-! CHECK:   %[[IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
-! CHECK:   fir.store %[[IV1_I32]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IV1]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV1_DECL:.*]]:2 = hlfir.declare %[[IV1_MEM]]
 ! CHECK:   %[[IV0_LD:.*]] = fir.load %[[IV0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[SUB:.*]] = arith.subi %[[IV0_LD]], %{{.*}} : i32
@@ -460,9 +458,8 @@ subroutine target_exit_data_depend_iterator()
 
 ! CHECK-LABEL: func.func @_QPtarget_exit_data_depend_iterator()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_exit_data_depend_iteratorEa")
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
-! CHECK:   fir.store %[[IV_I32]] to %[[IV_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV]] to %[[IV_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
@@ -485,17 +482,14 @@ subroutine target_exit_data_depend_iterator_multi()
 ! CHECK-LABEL: func.func @_QPtarget_exit_data_depend_iterator_multi()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_exit_data_depend_iterator_multiEa")
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_exit_data_depend_iterator_multiEb")
-! CHECK: %[[C16_I32:.*]] = arith.constant 16 : i32
-! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
-! CHECK: %[[LB:.*]] = fir.convert %[[C16_I32]] : (i32) -> index
-! CHECK: %[[UB:.*]] = fir.convert %[[C1_I32]] : (i32) -> index
-! CHECK: %[[CM1_I32:.*]] = arith.constant -1 : i32
-! CHECK: %[[STEP:.*]] = fir.convert %[[CM1_I32]] : (i32) -> index
-! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
+! CHECK: %[[LB:.*]] = arith.constant 16 : i32
+! CHECK: %[[UB:.*]] = arith.constant 1 : i32
+! CHECK: %[[STEP:.*]] = arith.constant -1 : i32
+! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: i32) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
 ! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
-! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
+! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: i32) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
 ! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
@@ -517,9 +511,8 @@ subroutine target_update_depend_iterator()
 
 ! CHECK-LABEL: func.func @_QPtarget_update_depend_iterator()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_update_depend_iteratorEa")
-! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
-! CHECK:   fir.store %[[IV_I32]] to %[[IV_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV]] to %[[IV_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]]
 ! CHECK:   %[[IV_LD:.*]] = fir.load %[[IV_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_I64:.*]] = fir.convert %[[IV_LD]] : (i32) -> i64
@@ -547,11 +540,11 @@ subroutine target_update_depend_iterator_multi()
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_update_depend_iterator_multiEa")
 ! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) uniq_name("_QFtarget_update_depend_iterator_multiEb")
 ! CHECK: %[[X:.*]]:2 = hlfir.declare %{{.*}} uniq_name("_QFtarget_update_depend_iterator_multiEx")
-! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
-! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR2:.*]] = hlfir.designate %[[B]]#0 (%{{.*}})
 ! CHECK:   omp.yield(%{{.*}} : !llvm.ptr)
 ! CHECK: } -> !omp.iterated<!llvm.ptr>
diff --git a/flang/test/Lower/OpenMP/iterator-empty-range.f90 b/flang/test/Lower/OpenMP/iterator-empty-range.f90
index dcdd8752dea945..874bcb549808f5 100644
--- a/flang/test/Lower/OpenMP/iterator-empty-range.f90
+++ b/flang/test/Lower/OpenMP/iterator-empty-range.f90
@@ -11,10 +11,8 @@ subroutine depend_empty_positive(a, m, d)
 end
 ! CHECK-LABEL: define {{.*}} @depend_empty_positive_(
 ! CHECK: [[M:%.*]] = load i32, ptr
-! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
 ! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
-! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
-! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 %{{.*}}
 ! CHECK: [[SIZE:%.*]] = mul {{.*}}i64 [[COUNT]], 24
 ! CHECK: [[LIST:%.*]] = {{.*}}call ptr @malloc(i64 [[SIZE]])
 ! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
@@ -34,10 +32,8 @@ subroutine affinity_empty_positive(a, m, d)
 end
 ! CHECK-LABEL: define {{.*}} @affinity_empty_positive_(
 ! CHECK: [[M:%.*]] = load i32, ptr
-! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
 ! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
-! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
-! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 %{{.*}}
 ! CHECK: [[LIST:%.*]] = alloca { i64, i64, i32 }, i64 [[COUNT]]
 ! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
 ! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
@@ -56,17 +52,16 @@ subroutine depend_empty_negative(a, m, d)
 end
 ! CHECK-LABEL: define {{.*}} @depend_empty_negative_(
 ! CHECK: [[M:%.*]] = load i32, ptr
-! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i65
-! CHECK: [[SPAN:%.*]] = sub nsw i65 3, [[WIDE]]
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i33
+! CHECK: [[SPAN:%.*]] = sub nsw i33 3, [[WIDE]]
 ! CHECK: [[EMPTY:%.*]] = icmp sgt i32 [[M]], 3
-! CHECK: [[HALF:%.*]] = lshr i65 [[SPAN]], 1
-! CHECK: [[HALF64:%.*]] = trunc {{.*}}i65 [[HALF]] to i64
-! CHECK: [[NONEMPTY:%.*]] = add i64 [[HALF64]], 1
+! CHECK: [[HALF:%.*]] = lshr i33 [[SPAN]], 1
+! CHECK: [[NONEMPTY33:%.*]] = add {{.*}}i33 [[HALF]], 1
+! CHECK: [[NONEMPTY:%.*]] = zext i33 [[NONEMPTY33]] to i64
 ! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
 ! CHECK: [[SIZE:%.*]] = mul {{.*}}i64 [[COUNT]], 24
 ! CHECK: [[LIST:%.*]] = {{.*}}call ptr @malloc(i64 [[SIZE]])
-! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
-! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK-NEXT: br i1 [[EMPTY]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
 ! CHECK: [[BODY]]:
 ! CHECK: sdiv i32
 ! CHECK: [[CONT]]:
@@ -82,16 +77,15 @@ subroutine affinity_empty_negative(a, m, d)
 end
 ! CHECK-LABEL: define {{.*}} @affinity_empty_negative_(
 ! CHECK: [[M:%.*]] = load i32, ptr
-! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i65
-! CHECK: [[SPAN:%.*]] = sub nsw i65 3, [[WIDE]]
+! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i33
+! CHECK: [[SPAN:%.*]] = sub nsw i33 3, [[WIDE]]
 ! CHECK: [[EMPTY:%.*]] = icmp sgt i32 [[M]], 3
-! CHECK: [[HALF:%.*]] = lshr i65 [[SPAN]], 1
-! CHECK: [[HALF64:%.*]] = trunc {{.*}}i65 [[HALF]] to i64
-! CHECK: [[NONEMPTY:%.*]] = add i64 [[HALF64]], 1
+! CHECK: [[HALF:%.*]] = lshr i33 [[SPAN]], 1
+! CHECK: [[NONEMPTY33:%.*]] = add {{.*}}i33 [[HALF]], 1
+! CHECK: [[NONEMPTY:%.*]] = zext i33 [[NONEMPTY33]] to i64
 ! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
 ! CHECK: [[LIST:%.*]] = alloca { i64, i64, i32 }, i64 [[COUNT]]
-! CHECK: [[ZERO:%.*]] = icmp eq i64 [[COUNT]], 0
-! CHECK-NEXT: br i1 [[ZERO]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
+! CHECK: br i1 [[EMPTY]], label %[[CONT:[^,]+]], label %[[BODY:.*]]
 ! CHECK: [[BODY]]:
 ! CHECK: sdiv i32
 ! CHECK: [[CONT]]:
@@ -109,10 +103,8 @@ subroutine depend_empty_product(a, m, n, d)
 ! CHECK-LABEL: define {{.*}} @depend_empty_product_(
 ! CHECK: [[M:%.*]] = load i32, ptr
 ! CHECK: [[N:%.*]] = load i32, ptr
-! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
 ! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
-! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
-! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 %{{.*}}
 ! CHECK: [[NCOUNT:%.*]] = {{.*}}call i32 @llvm.smax.i32(i32 [[N]], i32 0)
 ! CHECK: [[N64:%.*]] = zext {{.*}}i32 [[NCOUNT]] to i64
 ! CHECK: [[TOTAL:%.*]] = mul {{.*}}i64 [[COUNT]], [[N64]]
@@ -136,10 +128,8 @@ subroutine affinity_empty_product(a, m, n, d)
 ! CHECK-LABEL: define {{.*}} @affinity_empty_product_(
 ! CHECK: [[M:%.*]] = load i32, ptr
 ! CHECK: [[N:%.*]] = load i32, ptr
-! CHECK: [[WIDE:%.*]] = sext i32 [[M]] to i64
 ! CHECK: [[EMPTY:%.*]] = icmp slt i32 [[M]], 3
-! CHECK: [[NONEMPTY:%.*]] = add nsw i64 [[WIDE]], -2
-! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 [[NONEMPTY]]
+! CHECK: [[COUNT:%.*]] = select i1 [[EMPTY]], i64 0, i64 %{{.*}}
 ! CHECK: [[NCOUNT:%.*]] = {{.*}}call i32 @llvm.smax.i32(i32 [[N]], i32 0)
 ! CHECK: [[N64:%.*]] = zext {{.*}}i32 [[NCOUNT]] to i64
 ! CHECK: [[TOTAL:%.*]] = mul {{.*}}i64 [[COUNT]], [[N64]]
@@ -280,3 +270,45 @@ subroutine depend_retained_empty(a, m, n)
 ! CHECK: %[[COUNT:.*]] = trunc i64 %[[TRIPS]] to i32
 ! CHECK: call i32 @__kmpc_omp_task_with_deps(
 ! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 %[[COUNT]],
+
+! Ranges keep the iterator's kind; narrowing these bounds would empty the range.
+subroutine depend_wide_kind(a)
+  integer :: a(3)
+  integer(16) :: lb, ub
+  lb = 9223372036854775807_16
+  ub = 9223372036854775809_16
+  !$omp task depend(iterator(integer(16) :: i = lb:ub), in: a(i-lb+1))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @depend_wide_kind_(
+! CHECK: %[[IV:.*]] = phi i64 [ 0, %entry ]
+! CHECK: getelementptr {{.*}}[4 x i8], ptr %{{[0-9]+}}, i64 %[[IV]]
+! CHECK: icmp eq i64 %{{.*}}, 3
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 3,
+
+! The step is wider than the iterator's kind; narrowing it would empty {-128}.
+subroutine depend_wide_step(a)
+  integer :: a(-200:200)
+  !$omp task depend(iterator(integer(1) :: i = -128:-1:200), in: a(i))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @depend_wide_step_(
+! CHECK: getelementptr {{.*}} ptr %{{[0-9]+}}, i64 288
+! CHECK: call i32 @__kmpc_omp_task_with_deps(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 1,
+
+subroutine affinity_wide_kind(a)
+  integer :: a(3)
+  integer(16) :: lb, ub
+  lb = 9223372036854775807_16
+  ub = 9223372036854775809_16
+  !$omp task affinity(iterator(integer(16) :: i = lb:ub): a(i-lb+1))
+  !$omp end task
+end subroutine
+
+! CHECK-LABEL: define {{.*}} @affinity_wide_kind_(
+! CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(
+! CHECK-SAME: ptr {{[^,]+}}, i32 {{[^,]+}}, ptr {{[^,]+}}, i32 3,
diff --git a/flang/test/Lower/OpenMP/iterator-source-occurrences.f90 b/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
index 4c89d5c827538c..4a8832385ca913 100644
--- a/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
+++ b/flang/test/Lower/OpenMP/iterator-source-occurrences.f90
@@ -17,31 +17,26 @@ subroutine depend_folded(a, m, d, i)
 ! CHECK: %[[A:.*]]:2 = hlfir.declare
 ! CHECK-SAME: uniq_name("_QFdepend_foldedEa")
 ! CHECK: %[[M:.*]]:2 = hlfir.declare {{.*}}uniq_name("{{.*}}Em")
-! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
-! CHECK: %[[MVAL:.*]] = fir.load %[[M]]#0
-! CHECK: %[[ILB:.*]] = fir.convert %[[ONE]] : (i32) -> index
-! CHECK: %[[IUB:.*]] = fir.convert %[[MVAL]] : (i32) -> index
-! CHECK: %[[ISTEP:.*]] = arith.constant 1 : index
-! CHECK: %[[JONE:.*]] = arith.constant 1 : i32
-! CHECK: %[[TWO:.*]] = arith.constant 2 : i32
-! CHECK: %[[JLB:.*]] = fir.convert %[[JONE]] : (i32) -> index
-! CHECK: %[[JUB:.*]] = fir.convert %[[TWO]] : (i32) -> index
-! CHECK: %[[JSTEP:.*]] = arith.constant 1 : index
-! CHECK: %[[IT_IJ:.*]] = omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK: %[[ILB:.*]] = arith.constant 1 : i32
+! CHECK: %[[IUB:.*]] = fir.load %[[M]]#0
+! CHECK: %[[ISTEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[JLB:.*]] = arith.constant 1 : i32
+! CHECK: %[[JUB:.*]] = arith.constant 2 : i32
+! CHECK: %[[JSTEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[IT_IJ:.*]] = omp.iterator(%{{.*}}: i32, %{{.*}}: i32) =
 ! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]],
 ! CHECK-SAME: %[[JLB]] to %[[JUB]] step %[[JSTEP]])
 ! CHECK: arith.divsi
 ! CHECK: omp.yield
-! CHECK: %[[IT_I:.*]] = omp.iterator(%[[I:.*]]: index) =
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[I:.*]]: i32) =
 ! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]])
 ! CHECK: %[[FIRST:.*]] = arith.constant 1 : index
 ! CHECK: %[[FIXED:.*]] = hlfir.designate %[[A]]#0 (%[[FIRST]])
 ! CHECK: %[[FIXED_PTR:.*]] = fir.convert %[[FIXED]]
 ! CHECK: omp.yield(%[[FIXED_PTR]] : !llvm.ptr)
-! CHECK: %[[IT_J:.*]] = omp.iterator(%[[J:.*]]: index) =
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[J:.*]]: i32) =
 ! CHECK-SAME: (%[[JLB]] to %[[JUB]] step %[[JSTEP]])
-! CHECK: %[[JVAL:.*]] = fir.convert %[[J]] : (index) -> i32
-! CHECK: fir.store %[[JVAL]] to %[[JMEM:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[J]] to %[[JMEM:.*]] : !fir.ref<i32>
 ! CHECK: %[[JDECL:.*]]:2 = hlfir.declare %[[JMEM]]
 ! CHECK: %[[JLOAD:.*]] = fir.load %[[JDECL]]#0
 ! CHECK: %[[JIDX:.*]] = fir.convert %[[JLOAD]] : (i32) -> i64
@@ -64,7 +59,7 @@ subroutine depend_shadowed(a, b, m, i)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPdepend_shadowed(
-! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.iterator(%{{[^,:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK-NOT: omp.iterator
 ! CHECK: omp.task
@@ -81,32 +76,27 @@ subroutine affinity_folded(a, m, d, i)
 ! CHECK: %[[A:.*]]:2 = hlfir.declare
 ! CHECK-SAME: uniq_name("_QFaffinity_foldedEa")
 ! CHECK: %[[M:.*]]:2 = hlfir.declare {{.*}}uniq_name("{{.*}}Em")
-! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
-! CHECK: %[[MVAL:.*]] = fir.load %[[M]]#0
-! CHECK: %[[ILB:.*]] = fir.convert %[[ONE]] : (i32) -> index
-! CHECK: %[[IUB:.*]] = fir.convert %[[MVAL]] : (i32) -> index
-! CHECK: %[[ISTEP:.*]] = arith.constant 1 : index
-! CHECK: %[[JONE:.*]] = arith.constant 1 : i32
-! CHECK: %[[TWO:.*]] = arith.constant 2 : i32
-! CHECK: %[[JLB:.*]] = fir.convert %[[JONE]] : (i32) -> index
-! CHECK: %[[JUB:.*]] = fir.convert %[[TWO]] : (i32) -> index
-! CHECK: %[[JSTEP:.*]] = arith.constant 1 : index
-! CHECK: %[[IT_IJ:.*]] = omp.iterator(%{{.*}}: index, %{{.*}}: index) =
+! CHECK: %[[ILB:.*]] = arith.constant 1 : i32
+! CHECK: %[[IUB:.*]] = fir.load %[[M]]#0
+! CHECK: %[[ISTEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[JLB:.*]] = arith.constant 1 : i32
+! CHECK: %[[JUB:.*]] = arith.constant 2 : i32
+! CHECK: %[[JSTEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[IT_IJ:.*]] = omp.iterator(%{{.*}}: i32, %{{.*}}: i32) =
 ! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]],
 ! CHECK-SAME: %[[JLB]] to %[[JUB]] step %[[JSTEP]])
 ! CHECK: arith.divsi
 ! CHECK: omp.yield
-! CHECK: %[[IT_I:.*]] = omp.iterator(%[[I:.*]]: index) =
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[I:.*]]: i32) =
 ! CHECK-SAME: (%[[ILB]] to %[[IUB]] step %[[ISTEP]])
 ! CHECK: %[[FIRST:.*]] = arith.constant 1 : index
 ! CHECK: %[[FIXED:.*]] = hlfir.designate %[[A]]#0 (%[[FIRST]])
 ! CHECK: %[[FIXED_PTR:.*]] = fir.convert %[[FIXED]]
 ! CHECK: %[[FIXED_ENTRY:.*]] = omp.affinity_entry %[[FIXED_PTR]],
 ! CHECK: omp.yield(%[[FIXED_ENTRY]] :
-! CHECK: %[[IT_J:.*]] = omp.iterator(%[[J:.*]]: index) =
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[J:.*]]: i32) =
 ! CHECK-SAME: (%[[JLB]] to %[[JUB]] step %[[JSTEP]])
-! CHECK: %[[JVAL:.*]] = fir.convert %[[J]] : (index) -> i32
-! CHECK: fir.store %[[JVAL]] to %[[JMEM:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[J]] to %[[JMEM:.*]] : !fir.ref<i32>
 ! CHECK: %[[JDECL:.*]]:2 = hlfir.declare %[[JMEM]]
 ! CHECK: %[[JLOAD:.*]] = fir.load %[[JDECL]]#0
 ! CHECK: %[[JIDX:.*]] = fir.convert %[[JLOAD]] : (i32) -> i64
@@ -132,7 +122,7 @@ subroutine affinity_shadowed(a, b, m, i)
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPaffinity_shadowed(
-! CHECK: omp.iterator(%{{[^,:]+}}: index) =
+! CHECK: omp.iterator(%{{[^,:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK-NOT: omp.iterator
 ! CHECK: omp.task
@@ -150,9 +140,9 @@ subroutine depend_equal_designators(a, m)
   !$omp end task
 end
 ! CHECK-LABEL: func.func @_QPdepend_equal_designators(
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
-! CHECK: omp.iterator(%{{[^:]+}}: index, %{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32, %{{[^:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK-NOT: omp.iterator
 ! CHECK: omp.task depend(
@@ -163,9 +153,9 @@ subroutine affinity_equal_designators(a, m)
   !$omp end task
 end
 ! CHECK-LABEL: func.func @_QPaffinity_equal_designators(
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
-! CHECK: omp.iterator(%{{[^:]+}}: index, %{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32, %{{[^:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK-NOT: omp.iterator
 ! CHECK: omp.task affinity(
@@ -178,9 +168,9 @@ subroutine depend_scoped_references(a, m)
   !$omp end task
 end
 ! CHECK-LABEL: func.func @_QPdepend_scoped_references(
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK: omp.task depend(
 
@@ -197,15 +187,15 @@ subroutine target_folded_reference(a, m)
   !$omp target exit data map(from:a) depend(iterator(i=1:m), in: a(1+0*i))
 end
 ! CHECK-LABEL: func.func @_QPtarget_folded_reference(
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK: omp.target
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK: omp.target_enter_data
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK: omp.target_update
-! CHECK: omp.iterator(%{{[^:]+}}: index) =
+! CHECK: omp.iterator(%{{[^:]+}}: i32) =
 ! CHECK: omp.yield
 ! CHECK: omp.target_exit_data
diff --git a/flang/test/Lower/OpenMP/task-affinity.f90 b/flang/test/Lower/OpenMP/task-affinity.f90
index 813fb6f23251f6..331570895b37d5 100644
--- a/flang/test/Lower/OpenMP/task-affinity.f90
+++ b/flang/test/Lower/OpenMP/task-affinity.f90
@@ -273,15 +273,12 @@ subroutine affinity_unused_iterator(m)
 ! CHECK-SAME: uniq_name("_QFaffinity_unused_iteratorEa")
 ! CHECK: %[[M:.*]]:2 = hlfir.declare
 ! CHECK-SAME: uniq_name("_QFaffinity_unused_iteratorEm")
-! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
-! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
-! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
-! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
-! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
-! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK: %[[I_LB:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: i32) =
 ! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
-! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
-! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[IV_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
@@ -315,20 +312,15 @@ subroutine affinity_per_locator(m)
 ! CHECK-SAME: uniq_name("_QFaffinity_per_locatorEc")
 ! CHECK: %[[M:.*]]:2 = hlfir.declare
 ! CHECK-SAME: uniq_name("_QFaffinity_per_locatorEm")
-! CHECK: %[[I_LB32:.*]] = arith.constant 1 : i32
-! CHECK: %[[I_UB32:.*]] = arith.constant 2 : i32
-! CHECK: %[[I_LB:.*]] = fir.convert %[[I_LB32]] : (i32) -> index
-! CHECK: %[[I_UB:.*]] = fir.convert %[[I_UB32]] : (i32) -> index
-! CHECK: %[[I_STEP:.*]] = arith.constant 1 : index
-! CHECK: %[[J_LB32:.*]] = arith.constant 3 : i32
-! CHECK: %[[J_UB32:.*]] = fir.load %[[M]]#0 : !fir.ref<i32>
-! CHECK: %[[J_LB:.*]] = fir.convert %[[J_LB32]] : (i32) -> index
-! CHECK: %[[J_UB:.*]] = fir.convert %[[J_UB32]] : (i32) -> index
-! CHECK: %[[J_STEP:.*]] = arith.constant 1 : index
-! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: index) =
+! CHECK: %[[I_LB:.*]] = arith.constant 1 : i32
+! CHECK: %[[I_UB:.*]] = arith.constant 2 : i32
+! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[J_LB:.*]] = arith.constant 3 : i32
+! CHECK: %[[J_UB:.*]] = fir.load %[[M]]#0 : !fir.ref<i32>
+! CHECK: %[[J_STEP:.*]] = arith.constant 1 : i32
+! CHECK: %[[IT_I:.*]] = omp.iterator(%[[IV_I:.*]]: i32) =
 ! CHECK-SAME: (%[[I_LB]] to %[[I_UB]] step %[[I_STEP]]) {
-! CHECK: %[[V32_I:.*]] = fir.convert %[[IV_I]] : (index) -> i32
-! CHECK: fir.store %[[V32_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[IV_I]] to %[[MEM_I:.*]] : !fir.ref<i32>
 ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[MEM_I]]
 ! CHECK: %[[LD_I:.*]] = fir.load %[[DECL_I]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_I:.*]] = fir.convert %[[LD_I]] : (i32) -> i64
@@ -340,10 +332,9 @@ subroutine affinity_per_locator(m)
 ! CHECK: omp.yield(%[[ENTRY_I]] :
 ! CHECK-SAME: !omp.affinity_entry_ty<!fir.ref<i8>, i64>)
 ! CHECK: } -> !omp.iterated<!omp.affinity_entry_ty<!fir.ref<i8>, i64>>
-! CHECK: %[[IT_J:.*]] = omp.iterator(%[[IV_J:.*]]: index) =
+! CHECK: %[[IT_J:.*]] = omp.iterator(%[[IV_J:.*]]: i32) =
 ! CHECK-SAME: (%[[J_LB]] to %[[J_UB]] step %[[J_STEP]]) {
-! CHECK: %[[V32_J:.*]] = fir.convert %[[IV_J]] : (index) -> i32
-! CHECK: fir.store %[[V32_J]] to %[[MEM_J:.*]] : !fir.ref<i32>
+! CHECK: fir.store %[[IV_J]] to %[[MEM_J:.*]] : !fir.ref<i32>
 ! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[MEM_J]]
 ! CHECK: %[[LD_J:.*]] = fir.load %[[DECL_J]]#0 : !fir.ref<i32>
 ! CHECK: %[[IDX_J:.*]] = fir.convert %[[LD_J]] : (i32) -> i64
@@ -380,9 +371,8 @@ subroutine task_affinity_iterator_simple()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_simple()
-! CHECK: %[[ITERATED:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
-! CHECK:   fir.store %[[IV_I32]] to %[[IV_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITERATED:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV]] to %[[IV_MEM:.*]] : !fir.ref<i32>
 ! Iterator IV temp must be named in the compiler-generated namespace ("_QQ"
 ! prefix) so it is not emitted as a bogus user local in DWARF under -g.
 ! CHECK:   %[[IV_DECL:.*]]:2 = hlfir.declare %[[IV_MEM]] uniq_name("_QQ{{.*}}.omp.iter")
@@ -412,9 +402,8 @@ subroutine task_affinity_iterator_nondefault_lb()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_nondefault_lb()
-! CHECK: %[[ITERATED_NDLB:.*]] = omp.iterator(%[[IV_NDLB:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV_NDLB_I32:.*]] = fir.convert %[[IV_NDLB]] : (index) -> i32
-! CHECK:   fir.store %[[IV_NDLB_I32]] to %[[IV_NDLB_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITERATED_NDLB:.*]] = omp.iterator(%[[IV_NDLB:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV_NDLB]] to %[[IV_NDLB_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV_NDLB_DECL:.*]]:2 = hlfir.declare %[[IV_NDLB_MEM]]
 ! CHECK:   %[[IV_NDLB_LD:.*]] = fir.load %[[IV_NDLB_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV_NDLB_I64:.*]] = fir.convert %[[IV_NDLB_LD]] : (i32) -> i64
@@ -443,12 +432,10 @@ subroutine task_affinity_iterator_nondefault_lb_2d()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_nondefault_lb_2d()
-! CHECK: %[[ITERATED_NDLB2:.*]] = omp.iterator(%[[IV0_NDLB2:.*]]: index, %[[IV1_NDLB2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV0_NDLB2_I32:.*]] = fir.convert %[[IV0_NDLB2]] : (index) -> i32
-! CHECK:   fir.store %[[IV0_NDLB2_I32]] to %[[IV0_NDLB2_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITERATED_NDLB2:.*]] = omp.iterator(%[[IV0_NDLB2:.*]]: i32, %[[IV1_NDLB2:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV0_NDLB2]] to %[[IV0_NDLB2_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV0_NDLB2_DECL:.*]]:2 = hlfir.declare %[[IV0_NDLB2_MEM]]
-! CHECK:   %[[IV1_NDLB2_I32:.*]] = fir.convert %[[IV1_NDLB2]] : (index) -> i32
-! CHECK:   fir.store %[[IV1_NDLB2_I32]] to %[[IV1_NDLB2_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IV1_NDLB2]] to %[[IV1_NDLB2_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV1_NDLB2_DECL:.*]]:2 = hlfir.declare %[[IV1_NDLB2_MEM]]
 ! CHECK:   %[[IV0_NDLB2_LD:.*]] = fir.load %[[IV0_NDLB2_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV0_NDLB2_I64:.*]] = fir.convert %[[IV0_NDLB2_LD]] : (i32) -> i64
@@ -483,12 +470,10 @@ subroutine task_affinity_iterator_multi_dimension()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_multi_dimension()
-! CHECK: %[[ITER:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
-! CHECK:   fir.store %[[IV0_I32]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITER:.*]] = omp.iterator(%[[IV0:.*]]: i32, %[[IV1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV0]] to %[[IV0_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV0_DECL:.*]]:2 = hlfir.declare %[[IV0_MEM]]
-! CHECK:   %[[IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
-! CHECK:   fir.store %[[IV1_I32]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IV1]] to %[[IV1_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IV1_DECL:.*]]:2 = hlfir.declare %[[IV1_MEM]]
 ! CHECK:   %[[IV0_LD:.*]] = fir.load %[[IV0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IV0_I64:.*]] = fir.convert %[[IV0_LD]] : (i32) -> i64
@@ -517,12 +502,10 @@ subroutine task_affinity_iterator_reordered()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_reordered()
-! CHECK: %[[ITER:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[RO_IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
-! CHECK:   fir.store %[[RO_IV0_I32]] to %[[RO_IV0_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITER:.*]] = omp.iterator(%[[IV0:.*]]: i32, %[[IV1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IV0]] to %[[RO_IV0_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[RO_IV0_DECL:.*]]:2 = hlfir.declare %[[RO_IV0_MEM]]
-! CHECK:   %[[RO_IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
-! CHECK:   fir.store %[[RO_IV1_I32]] to %[[RO_IV1_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IV1]] to %[[RO_IV1_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[RO_IV1_DECL:.*]]:2 = hlfir.declare %[[RO_IV1_MEM]]
 ! CHECK:   %[[RO_IV1_LD:.*]] = fir.load %[[RO_IV1_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[RO_IV1_I64:.*]] = fir.convert %[[RO_IV1_LD]] : (i32) -> i64
@@ -546,12 +529,10 @@ subroutine task_affinity_iterator_expr_subscript()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_expr_subscript()
-! CHECK: %[[ITER2:.*]] = omp.iterator(%[[IVA:.*]]: index, %[[IVB:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IVA_I32:.*]] = fir.convert %[[IVA]] : (index) -> i32
-! CHECK:   fir.store %[[IVA_I32]] to %[[IVA_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITER2:.*]] = omp.iterator(%[[IVA:.*]]: i32, %[[IVB:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IVA]] to %[[IVA_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IVA_DECL:.*]]:2 = hlfir.declare %[[IVA_MEM]]
-! CHECK:   %[[IVB_I32:.*]] = fir.convert %[[IVB]] : (index) -> i32
-! CHECK:   fir.store %[[IVB_I32]] to %[[IVB_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IVB]] to %[[IVB_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IVB_DECL:.*]]:2 = hlfir.declare %[[IVB_MEM]]
 ! CHECK:   %[[IVA_LD:.*]] = fir.load %[[IVA_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C1_I32:.*]] = arith.constant 1 : i32
@@ -577,12 +558,10 @@ subroutine task_affinity_iterator_section_subscript()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_section_subscript()
-! CHECK: %[[ITER3:.*]] = omp.iterator(%[[IVS0:.*]]: index, %[[IVS1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IVS0_I32:.*]] = fir.convert %[[IVS0]] : (index) -> i32
-! CHECK:   fir.store %[[IVS0_I32]] to %[[IVS0_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITER3:.*]] = omp.iterator(%[[IVS0:.*]]: i32, %[[IVS1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IVS0]] to %[[IVS0_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IVS0_DECL:.*]]:2 = hlfir.declare %[[IVS0_MEM]]
-! CHECK:   %[[IVS1_I32:.*]] = fir.convert %[[IVS1]] : (index) -> i32
-! CHECK:   fir.store %[[IVS1_I32]] to %[[IVS1_MEM:.*]] : !fir.ref<i32>
+! CHECK:   fir.store %[[IVS1]] to %[[IVS1_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IVS1_DECL:.*]]:2 = hlfir.declare %[[IVS1_MEM]]
 ! CHECK:   %[[IVS0_LD:.*]] = fir.load %[[IVS0_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IVS0_I64:.*]] = fir.convert %[[IVS0_LD]] : (i32) -> i64
@@ -615,9 +594,8 @@ subroutine task_affinity_iterator_section_implicit_lower()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_section_implicit_lower()
-! CHECK: %[[ITER4:.*]] = omp.iterator(%[[IVT0:.*]]: index, %[[IVT1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IVT1_I32:.*]] = fir.convert %[[IVT1]] : (index) -> i32
-! CHECK:   fir.store %[[IVT1_I32]] to %[[IVT1_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITER4:.*]] = omp.iterator(%[[IVT0:.*]]: i32, %[[IVT1:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IVT1]] to %[[IVT1_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IVT1_DECL:.*]]:2 = hlfir.declare %[[IVT1_MEM]]
 ! CHECK:   %[[C1_IDX:.*]] = arith.constant 1 : index
 ! CHECK:   %[[IVT1_LD:.*]] = fir.load %[[IVT1_DECL]]#0 : !fir.ref<i32>
@@ -643,9 +621,8 @@ subroutine task_affinity_iterator_char_simple()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_char_simple()
-! CHECK: %[[ITER5:.*]] = omp.iterator(%[[IVC:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IVC_I32:.*]] = fir.convert %[[IVC]] : (index) -> i32
-! CHECK:   fir.store %[[IVC_I32]] to %[[IVC_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITER5:.*]] = omp.iterator(%[[IVC:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IVC]] to %[[IVC_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IVC_DECL:.*]]:2 = hlfir.declare %[[IVC_MEM]]
 ! CHECK:   %[[IVC_LD:.*]] = fir.load %[[IVC_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[IVC_I64:.*]] = fir.convert %[[IVC_LD]] : (i32) -> i64
@@ -671,9 +648,8 @@ subroutine task_affinity_iterator_char_expr_subscript()
 end subroutine
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_char_expr_subscript()
-! CHECK: %[[ITER6:.*]] = omp.iterator(%[[IVC2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
-! CHECK:   %[[IVC2_I32:.*]] = fir.convert %[[IVC2]] : (index) -> i32
-! CHECK:   fir.store %[[IVC2_I32]] to %[[IVC2_MEM:.*]] : !fir.ref<i32>
+! CHECK: %[[ITER6:.*]] = omp.iterator(%[[IVC2:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK:   fir.store %[[IVC2]] to %[[IVC2_MEM:.*]] : !fir.ref<i32>
 ! CHECK:   %[[IVC2_DECL:.*]]:2 = hlfir.declare %[[IVC2_MEM]]
 ! CHECK:   %[[IVC2_LD:.*]] = fir.load %[[IVC2_DECL]]#0 : !fir.ref<i32>
 ! CHECK:   %[[C1_I32_6:.*]] = arith.constant 1 : i32
@@ -703,7 +679,7 @@ subroutine task_affinity_iterator_char_runtime(n, l)
 
 ! CHECK-LABEL: func.func @_QPtask_affinity_iterator_char_runtime(
 ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) typeparams %{{.*}} uniq_name("_QFtask_affinity_iterator_char_runtimeEa")
-! CHECK: %[[ITER:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+! CHECK: %[[ITER:.*]] = omp.iterator(%[[IV:.*]]: i32) = ({{.*}} to {{.*}} step {{.*}}) {
 ! CHECK:   %[[COOR:.*]] = hlfir.designate %[[A]]#0 ({{.*}})
 ! CHECK:   %[[RAW:.*]]:2 = fir.unboxchar %[[COOR]]
 ! CHECK:   %[[ELEM:.*]] = fir.box_elesize %[[A]]#0 : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index
diff --git a/flang/test/Semantics/OpenMP/depend08.f90 b/flang/test/Semantics/OpenMP/depend08.f90
new file mode 100644
index 00000000000000..ca445b6c245f2b
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/depend08.f90
@@ -0,0 +1,17 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52
+
+subroutine depend_iterator_noninteger_iv(x)
+  integer :: x(10)
+  !ERROR: The iterator variable must be of integer type
+  !$omp task depend(iterator(real :: r = 1:3), in: x(int(r)))
+  !$omp end task
+end subroutine
+
+! The range is nonempty; truncating the bounds to 64 bits would reverse them.
+subroutine depend_iterator_wide_constants(x)
+  integer :: x(3)
+  !$omp task depend(iterator(integer(16) :: i = &
+  !$omp&    9223372036854775807_16:9223372036854775809_16), &
+  !$omp&    in: x(i - 9223372036854775806_16))
+  !$omp end task
+end subroutine



More information about the llvm-branch-commits mailing list