[Mlir-commits] [mlir] [mlir][OpenMP] Introduce 'omp.iterators' for OpenMP iterator modifiers (PR #182218)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Feb 24 14:58:59 PST 2026


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

>From 182a567c4bebc5add1676d463dbd0c340bb9b83e Mon Sep 17 00:00:00 2001
From: cchen <chichun.chen at hpe.com>
Date: Thu, 12 Feb 2026 17:57:40 -0600
Subject: [PATCH 1/2] [mlir][OpenMP] Introduce 'omp.iterators' for OpenMP
 iterator modifiers

`omp.iterators` provides information of induction variables and iterator
range in OpenMP iterator modifier.

Example:
```
  %it = omp.iterators(%i0: index, %i1: index) =
        (%lb0 to %ub0 step %st0,
         %lb1 to %ub1 step %st1) {
    omp.yield(%i0, %i1 : index, index)
  } -> !omp.iterated<!llvm.struct<(!llvm.ptr, i64)>>
```

Here's how we can use the omp.iteraters to generate multi-dimensional
loop in llvm ir:
```
  // Induction variables can be translated from the block arguments
  // in omp.iterators.
  // lbs, ubs, and steps is encoded in omp.iterators
  for (int i0 = lbs[0]; i0 < ubs[0]; i0 += steps[0]) {
      for (int i0 = lbs[1]; i1 < ubs[1]; i1 += steps[1]) {
          // the result of iterated is <ptr, i64> from the example
          iterated = omp.iterators(i, j);
      }
  }
```
---
 .../mlir/Dialect/OpenMP/OpenMPOpBase.td       |   7 ++
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |  47 +++++++-
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  | 108 ++++++++++++++++++
 mlir/test/Dialect/OpenMP/invalid.mlir         |  20 ++++
 mlir/test/Dialect/OpenMP/ops.mlir             |  29 +++++
 5 files changed, 206 insertions(+), 5 deletions(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td
index 5ad4e4b5b61d1..4dd8e91585a66 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td
@@ -38,6 +38,13 @@ def OpenMP_MapBoundsType : OpenMP_Type<"MapBounds", "map_bounds_ty"> {
   let summary = "Type for representing omp map clause bounds information";
 }
 
+def OpenMP_IteratedType : OpenMP_Type<"Iterated", "iterated"> {
+  let summary = "OpenMP iterator-produced list handle";
+
+  let parameters = (ins "Type":$elementType);
+  let assemblyFormat = "`<` $elementType `>`";
+}
+
 //===---------------------------------------------------------------------===//
 // OpenMP Canonical Loop Info Type
 //===---------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 0f51b08f87dc5..9705185656907 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -845,11 +845,11 @@ def SimdOp : OpenMP_Op<"simd", traits = [
   let hasRegionVerifier = 1;
 }
 
-
-def YieldOp : OpenMP_Op<"yield",
-    [Pure, ReturnLike, Terminator,
-     ParentOneOf<["AtomicUpdateOp", "DeclareReductionOp", "LoopNestOp",
-                  "PrivateClauseOp"]>]> {
+def YieldOp
+    : OpenMP_Op<"yield", [Pure, ReturnLike, Terminator,
+                          ParentOneOf<["AtomicUpdateOp", "DeclareReductionOp",
+                                       "LoopNestOp", "PrivateClauseOp",
+                                       "IteratorsOp"]>]> {
   let summary = "loop yield and termination operation";
   let description = [{
     "omp.yield" yields SSA values from the OpenMP dialect op region and
@@ -2300,4 +2300,41 @@ def DeclareSimdOp
   let hasVerifier = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// Iterators Op
+//===----------------------------------------------------------------------===//
+
+def IteratorsOp
+    : OpenMP_Op<"iterators", [AttrSizedOperandSegments,
+                              SingleBlockImplicitTerminator<"YieldOp">]> {
+  let summary = "OpenMP iterator modifier";
+  let description = [{
+    The result of `omp.iterators` is an abstract handle of type
+    `!omp.iterated<T>`, representing the list of yielded values. This handle
+    can be directly consumed by OpenMP clauses that accept iterator modifiers,
+    such as `affinity`, `map`, `to`, `from`, or `depend`.
+
+    Example:
+      %it = omp.iterators(%i, %j) =
+        (%lb_i to %ub_i step %st_i, %lb_j to %ub_j step %st_j) {
+        %addr = ...
+        omp.yield(%addr)
+      } -> !omp.iterated<ptr>
+  }];
+
+  let arguments = (ins Variadic<IntLikeType>:$lbs, Variadic<IntLikeType>:$ubs,
+      Variadic<IntLikeType>:$steps);
+  let regions = (region SizedRegion<1>:$region);
+  let results = (outs OpenMP_IteratedType:$iterated);
+
+  let assemblyFormat = [{
+    `(` custom<IteratorsHeader>($region,
+                                $lbs, $ubs, $steps,
+                                type($lbs), type($ubs), type($steps))
+    `->` qualified(type($iterated)) attr-dict
+  }];
+
+  let hasVerifier = 1;
+}
+
 #endif // OPENMP_OPS
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 601c970bc8a69..b55e278e08255 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4624,6 +4624,114 @@ static void printAffinityClause(OpAsmPrinter &p, Operation *op,
   }
 }
 
+//===----------------------------------------------------------------------===//
+// Parser, printer, and verifier for Iterator modifier
+//===----------------------------------------------------------------------===//
+
+static ParseResult
+parseIteratorsHeader(OpAsmParser &parser, Region &region,
+                     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &lbs,
+                     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &ubs,
+                     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &steps,
+                     SmallVectorImpl<Type> &lbTypes,
+                     SmallVectorImpl<Type> &ubTypes,
+                     SmallVectorImpl<Type> &stepTypes) {
+
+  llvm::SMLoc ivLoc = parser.getCurrentLocation();
+  SmallVector<OpAsmParser::Argument> ivArgs;
+
+  // Parse induction variables: %i : i32, %j : i32
+  if (parser.parseCommaSeparatedList([&]() -> ParseResult {
+        OpAsmParser::Argument &arg = ivArgs.emplace_back();
+        if (parser.parseArgument(arg))
+          return failure();
+
+        // Optional type, default to Index if not provided
+        if (succeeded(parser.parseOptionalColon())) {
+          if (parser.parseType(arg.type))
+            return failure();
+        } else {
+          arg.type = parser.getBuilder().getIndexType();
+        }
+        return success();
+      }))
+    return failure();
+
+  // ) = (
+  if (parser.parseRParen() || parser.parseEqual() || parser.parseLParen())
+    return failure();
+
+  // Parse Ranges: (%lb to %ub step %st, ...)
+  if (parser.parseCommaSeparatedList([&]() -> ParseResult {
+        OpAsmParser::UnresolvedOperand lb, ub, st;
+        if (parser.parseOperand(lb) || parser.parseKeyword("to") ||
+            parser.parseOperand(ub) || parser.parseKeyword("step") ||
+            parser.parseOperand(st))
+          return failure();
+
+        lbs.push_back(lb);
+        ubs.push_back(ub);
+        steps.push_back(st);
+        return success();
+      }))
+    return failure();
+
+  if (parser.parseRParen())
+    return failure();
+
+  if (ivArgs.size() != lbs.size())
+    return parser.emitError(ivLoc)
+           << "mismatch: " << ivArgs.size() << " variables but " << lbs.size()
+           << " ranges";
+
+  for (auto &arg : ivArgs) {
+    lbTypes.push_back(arg.type);
+    ubTypes.push_back(arg.type);
+    stepTypes.push_back(arg.type);
+  }
+
+  return parser.parseRegion(region, ivArgs);
+}
+
+static void printIteratorsHeader(OpAsmPrinter &p, Operation *op, Region &region,
+                                 ValueRange lbs, ValueRange ubs,
+                                 ValueRange steps, TypeRange, TypeRange,
+                                 TypeRange) {
+  Block &entry = region.front();
+
+  for (unsigned i = 0, e = entry.getNumArguments(); i < e; ++i) {
+    if (i != 0)
+      p << ", ";
+    p.printRegionArgument(entry.getArgument(i));
+  }
+  p << ") = (";
+
+  // (%lb0 to %ub0 step %step0, %lb1 to %ub1 step %step1, ...)
+  for (unsigned i = 0, e = lbs.size(); i < e; ++i) {
+    if (i)
+      p << ", ";
+    p << lbs[i] << " to " << ubs[i] << " step " << steps[i];
+  }
+  p << ") ";
+
+  p.printRegion(region, /*printEntryBlockArgs=*/false,
+                /*printBlockTerminators=*/true);
+}
+
+LogicalResult IteratorsOp::verify() {
+  auto iteratedTy = llvm::dyn_cast<omp::IteratedType>(getIterated().getType());
+  if (!iteratedTy)
+    return emitOpError() << "result must be omp.iterated<entry_ty>";
+
+  Block &b = getRegion().front();
+  auto yield = llvm::dyn_cast<omp::YieldOp>(b.getTerminator());
+
+  if (!yield)
+    return emitOpError() << "region must be terminated by omp.yield";
+
+  return success();
+}
+
 #define GET_ATTRDEF_CLASSES
 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
 
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 4ee9b2c58a5ef..23bc6a98b8e71 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3167,3 +3167,23 @@ func.func @omp_declare_simd_branch() -> () {
   omp.declare_simd inbranch notinbranch
   return
 }
+
+// -----
+
+func.func @iterators_bad_result_type(%lb : index, %ub : index, %st : index) {
+  // expected-error at +1 {{result #0 must be OpenMP iterator-produced list handle, but got 'index'}}
+  %0 = omp.iterators(%i: index) = (%lb to %ub step %st) {
+    omp.yield(%i : index)
+  } -> index
+  return
+}
+
+// -----
+
+func.func @iterators_missing_yield(%lb : index, %ub : index, %st : index) {
+  // expected-error at +1 {{region must be terminated by omp.yield}}
+  %0 = omp.iterators(%i: index) = (%lb to %ub step %st) {
+    func.return
+  } -> !omp.iterated<index>
+  return
+}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 5c2849cc9b5ea..6186ff35c8df7 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3550,3 +3550,32 @@ func.func @task_affinity_multi() {
   }
   return
 }
+
+// CHECK-LABEL: func.func @omp_iterators(
+func.func @omp_iterators(%lb : index, %ub : index, %step : index) -> () {
+  // CHECK: %[[IT:.*]] = omp.iterators(%[[IV:.*]]: index) = (%[[LB:.*]] to %[[UB:.*]] step %[[ST:.*]]) {
+  // CHECK:   omp.yield({{.*}} : index)
+  // CHECK: } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
+  %0 = omp.iterators(%arg0: index) = (%lb to %ub step %step) {
+    omp.yield(%arg0 : index)
+  } -> !omp.iterated<!llvm.struct<(!llvm.ptr, i64)>>
+  return
+}
+
+// CHECK-LABEL: func.func @omp_iterators_2d(
+func.func @omp_iterators_2d(%lb0 : index, %ub0 : index, %st0 : index,
+                            %lb1 : index, %ub1 : index, %st1 : index) -> () {
+  // CHECK: %[[IT:.*]] = omp.iterators(%[[IV0:.*]]: index, %[[IV1:.*]]: index) =
+  // CHECK-SAME: (%[[LB0:.*]] to %[[UB0:.*]] step %[[ST0:.*]],
+  // CHECK-SAME:  %[[LB1:.*]] to %[[UB1:.*]] step %[[ST1:.*]]) {
+  // CHECK: omp.yield(%[[IV0]], %[[IV1]] : index, index)
+  // CHECK: } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
+
+  %it = omp.iterators(%i0: index, %i1: index) =
+        (%lb0 to %ub0 step %st0,
+         %lb1 to %ub1 step %st1) {
+    omp.yield(%i0, %i1 : index, index)
+  } -> !omp.iterated<!llvm.struct<(!llvm.ptr, i64)>>
+
+  return
+}

>From 4e64dcbab6927752d4f4768eec5bbe58599c3c50 Mon Sep 17 00:00:00 2001
From: cchen <chichun.chen at hpe.com>
Date: Tue, 24 Feb 2026 16:17:28 -0600
Subject: [PATCH 2/2] Fix based on feedback

- omp.iterators -> omp.iterator
- add return type in verifier
- Use OpenMP_LoopRelatedClause in omp.iterator for consistent bounds
definition
---
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 23 +++++-----
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  | 36 ++++++++++------
 mlir/test/Dialect/OpenMP/invalid.mlir         | 28 ++++++++++--
 mlir/test/Dialect/OpenMP/ops.mlir             | 43 +++++++++++--------
 4 files changed, 85 insertions(+), 45 deletions(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 9705185656907..3cce660b43a33 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -849,7 +849,7 @@ def YieldOp
     : OpenMP_Op<"yield", [Pure, ReturnLike, Terminator,
                           ParentOneOf<["AtomicUpdateOp", "DeclareReductionOp",
                                        "LoopNestOp", "PrivateClauseOp",
-                                       "IteratorsOp"]>]> {
+                                       "IteratorOp"]>]> {
   let summary = "loop yield and termination operation";
   let description = [{
     "omp.yield" yields SSA values from the OpenMP dialect op region and
@@ -2301,36 +2301,35 @@ def DeclareSimdOp
 }
 
 //===----------------------------------------------------------------------===//
-// Iterators Op
+// Iterator Op
 //===----------------------------------------------------------------------===//
 
-def IteratorsOp
-    : OpenMP_Op<"iterators", [AttrSizedOperandSegments,
-                              SingleBlockImplicitTerminator<"YieldOp">]> {
+def IteratorOp : OpenMP_Op<"iterator",
+                           [AttrSizedOperandSegments,
+                            SingleBlockImplicitTerminator<"YieldOp">],
+                           clauses = [OpenMP_LoopRelatedClause]> {
   let summary = "OpenMP iterator modifier";
   let description = [{
-    The result of `omp.iterators` is an abstract handle of type
+    The result of `omp.iterator` is an abstract handle of type
     `!omp.iterated<T>`, representing the list of yielded values. This handle
     can be directly consumed by OpenMP clauses that accept iterator modifiers,
     such as `affinity`, `map`, `to`, `from`, or `depend`.
 
     Example:
-      %it = omp.iterators(%i, %j) =
+      %it = omp.iterator(%i, %j) =
         (%lb_i to %ub_i step %st_i, %lb_j to %ub_j step %st_j) {
         %addr = ...
         omp.yield(%addr)
       } -> !omp.iterated<ptr>
   }];
 
-  let arguments = (ins Variadic<IntLikeType>:$lbs, Variadic<IntLikeType>:$ubs,
-      Variadic<IntLikeType>:$steps);
   let regions = (region SizedRegion<1>:$region);
   let results = (outs OpenMP_IteratedType:$iterated);
 
   let assemblyFormat = [{
-    `(` custom<IteratorsHeader>($region,
-                                $lbs, $ubs, $steps,
-                                type($lbs), type($ubs), type($steps))
+    `(` custom<IteratorHeader>($region,
+                                $loop_lower_bounds, $loop_upper_bounds, $loop_steps,
+                                type($loop_lower_bounds), type($loop_upper_bounds), type($loop_steps))
     `->` qualified(type($iterated)) attr-dict
   }];
 
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index b55e278e08255..f2d039d7bf5ba 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4629,13 +4629,13 @@ static void printAffinityClause(OpAsmPrinter &p, Operation *op,
 //===----------------------------------------------------------------------===//
 
 static ParseResult
-parseIteratorsHeader(OpAsmParser &parser, Region &region,
-                     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &lbs,
-                     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &ubs,
-                     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &steps,
-                     SmallVectorImpl<Type> &lbTypes,
-                     SmallVectorImpl<Type> &ubTypes,
-                     SmallVectorImpl<Type> &stepTypes) {
+parseIteratorHeader(OpAsmParser &parser, Region &region,
+                    SmallVectorImpl<OpAsmParser::UnresolvedOperand> &lbs,
+                    SmallVectorImpl<OpAsmParser::UnresolvedOperand> &ubs,
+                    SmallVectorImpl<OpAsmParser::UnresolvedOperand> &steps,
+                    SmallVectorImpl<Type> &lbTypes,
+                    SmallVectorImpl<Type> &ubTypes,
+                    SmallVectorImpl<Type> &stepTypes) {
 
   llvm::SMLoc ivLoc = parser.getCurrentLocation();
   SmallVector<OpAsmParser::Argument> ivArgs;
@@ -4693,10 +4693,10 @@ parseIteratorsHeader(OpAsmParser &parser, Region &region,
   return parser.parseRegion(region, ivArgs);
 }
 
-static void printIteratorsHeader(OpAsmPrinter &p, Operation *op, Region &region,
-                                 ValueRange lbs, ValueRange ubs,
-                                 ValueRange steps, TypeRange, TypeRange,
-                                 TypeRange) {
+static void printIteratorHeader(OpAsmPrinter &p, Operation *op, Region &region,
+                                ValueRange lbs, ValueRange ubs,
+                                ValueRange steps, TypeRange, TypeRange,
+                                TypeRange) {
   Block &entry = region.front();
 
   for (unsigned i = 0, e = entry.getNumArguments(); i < e; ++i) {
@@ -4718,7 +4718,7 @@ static void printIteratorsHeader(OpAsmPrinter &p, Operation *op, Region &region,
                 /*printBlockTerminators=*/true);
 }
 
-LogicalResult IteratorsOp::verify() {
+LogicalResult IteratorOp::verify() {
   auto iteratedTy = llvm::dyn_cast<omp::IteratedType>(getIterated().getType());
   if (!iteratedTy)
     return emitOpError() << "result must be omp.iterated<entry_ty>";
@@ -4729,6 +4729,18 @@ LogicalResult IteratorsOp::verify() {
   if (!yield)
     return emitOpError() << "region must be terminated by omp.yield";
 
+  if (yield.getNumOperands() != 1)
+    return emitOpError()
+           << "omp.yield in omp.iterator region must yield exactly one value";
+
+  mlir::Type yieldedTy = yield.getOperand(0).getType();
+  mlir::Type elemTy = iteratedTy.getElementType();
+
+  if (yieldedTy != elemTy)
+    return emitOpError() << "omp.iterated element type (" << elemTy
+                         << ") does not match omp.yield operand type ("
+                         << yieldedTy << ")";
+
   return success();
 }
 
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 23bc6a98b8e71..bc508d66fbd5f 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3170,9 +3170,9 @@ func.func @omp_declare_simd_branch() -> () {
 
 // -----
 
-func.func @iterators_bad_result_type(%lb : index, %ub : index, %st : index) {
+func.func @iterator_bad_result_type(%lb : index, %ub : index, %st : index) {
   // expected-error at +1 {{result #0 must be OpenMP iterator-produced list handle, but got 'index'}}
-  %0 = omp.iterators(%i: index) = (%lb to %ub step %st) {
+  %0 = omp.iterator(%i: index) = (%lb to %ub step %st) {
     omp.yield(%i : index)
   } -> index
   return
@@ -3180,10 +3180,30 @@ func.func @iterators_bad_result_type(%lb : index, %ub : index, %st : index) {
 
 // -----
 
-func.func @iterators_missing_yield(%lb : index, %ub : index, %st : index) {
+func.func @iterator_missing_yield(%lb : index, %ub : index, %st : index) {
   // expected-error at +1 {{region must be terminated by omp.yield}}
-  %0 = omp.iterators(%i: index) = (%lb to %ub step %st) {
+  %0 = omp.iterator(%i: index) = (%lb to %ub step %st) {
     func.return
   } -> !omp.iterated<index>
   return
 }
+
+// -----
+
+func.func @iterator_yield_wrong_num_operands(%lb : index, %ub : index, %st : index) {
+  // expected-error at +1 {{omp.yield in omp.iterator region must yield exactly one value}}
+  %0 = omp.iterator(%i: index) = (%lb to %ub step %st) {
+    omp.yield(%i, %i : index, index)
+  } -> !omp.iterated<index>
+  return
+}
+
+// -----
+
+func.func @iterator_yield_type_mismatch(%lb : index, %ub : index, %st : index) {
+  // expected-error at +1 {{omp.iterated element type ('i64') does not match omp.yield operand type ('index')}}
+  %0 = omp.iterator(%i: index) = (%lb to %ub step %st) {
+    omp.yield(%i : index)
+  } -> !omp.iterated<i64>
+  return
+}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 6186ff35c8df7..7d73063321299 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3551,31 +3551,40 @@ func.func @task_affinity_multi() {
   return
 }
 
-// CHECK-LABEL: func.func @omp_iterators(
-func.func @omp_iterators(%lb : index, %ub : index, %step : index) -> () {
-  // CHECK: %[[IT:.*]] = omp.iterators(%[[IV:.*]]: index) = (%[[LB:.*]] to %[[UB:.*]] step %[[ST:.*]]) {
-  // CHECK:   omp.yield({{.*}} : index)
+// CHECK-LABEL: func.func @omp_iterator
+func.func @omp_iterator(%s2 : !llvm.struct<(ptr, i64)>) -> () {
+  // CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
+  // CHECK:   omp.yield(%{{.*}} : !llvm.struct<(ptr, i64)>)
   // CHECK: } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
-  %0 = omp.iterators(%arg0: index) = (%lb to %ub step %step) {
-    omp.yield(%arg0 : index)
-  } -> !omp.iterated<!llvm.struct<(!llvm.ptr, i64)>>
+  %lb = arith.constant 1 : index
+  %ub = arith.constant 4 : index
+  %st = arith.constant 1 : index
+
+  %0 = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+    omp.yield(%s2 : !llvm.struct<(ptr, i64)>)
+  } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
   return
 }
 
-// CHECK-LABEL: func.func @omp_iterators_2d(
-func.func @omp_iterators_2d(%lb0 : index, %ub0 : index, %st0 : index,
-                            %lb1 : index, %ub1 : index, %st1 : index) -> () {
-  // CHECK: %[[IT:.*]] = omp.iterators(%[[IV0:.*]]: index, %[[IV1:.*]]: index) =
-  // CHECK-SAME: (%[[LB0:.*]] to %[[UB0:.*]] step %[[ST0:.*]],
-  // CHECK-SAME:  %[[LB1:.*]] to %[[UB1:.*]] step %[[ST1:.*]]) {
-  // CHECK: omp.yield(%[[IV0]], %[[IV1]] : index, index)
+// CHECK-LABEL: func.func @omp_iterator_2d
+func.func @omp_iterator_2d(%s2 : !llvm.struct<(ptr, i64)>) -> () {
+  // CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) =
+  // CHECK-SAME: ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
+  // CHECK:   omp.yield(%{{.*}} : !llvm.struct<(ptr, i64)>)
   // CHECK: } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
 
-  %it = omp.iterators(%i0: index, %i1: index) =
+  %lb0 = arith.constant 1 : index
+  %ub0 = arith.constant 4 : index
+  %st0 = arith.constant 1 : index
+  %lb1 = arith.constant 2 : index
+  %ub1 = arith.constant 10 : index
+  %st1 = arith.constant 2 : index
+
+  %0 = omp.iterator(%iv0: index, %iv1: index) =
         (%lb0 to %ub0 step %st0,
          %lb1 to %ub1 step %st1) {
-    omp.yield(%i0, %i1 : index, index)
-  } -> !omp.iterated<!llvm.struct<(!llvm.ptr, i64)>>
+    omp.yield(%s2 : !llvm.struct<(ptr, i64)>)
+  } -> !omp.iterated<!llvm.struct<(ptr, i64)>>
 
   return
 }



More information about the Mlir-commits mailing list