https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/171825

>From d02544b205133749563f6222fd0e71c863226d3c Mon Sep 17 00:00:00 2001
From: skc7 <[email protected]>
Date: Thu, 11 Dec 2025 13:35:05 +0530
Subject: [PATCH 1/2] [OpenMP][MLIR] Add thread_limit with dims modifier
 support

---
 .../Optimizer/OpenMP/LowerWorkdistribute.cpp  |  16 +-
 .../mlir/Dialect/OpenMP/OpenMPClauses.td      |  29 +++-
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  72 ++++++++-
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      |   8 +
 mlir/test/Dialect/OpenMP/invalid.mlir         | 149 +++++++++++++++++-
 mlir/test/Dialect/OpenMP/ops.mlir             |   8 +-
 6 files changed, 264 insertions(+), 18 deletions(-)

diff --git a/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp 
b/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
index 7b61539984232..a3b9e5c76bdd2 100644
--- a/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
+++ b/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
@@ -766,6 +766,7 @@ FailureOr<omp::TargetOp> splitTargetData(omp::TargetOp 
targetOp,
       targetOp.getInReductionSymsAttr(), targetOp.getIsDevicePtrVars(),
       innerMapInfos, targetOp.getNowaitAttr(), targetOp.getPrivateVars(),
       targetOp.getPrivateSymsAttr(), targetOp.getPrivateNeedsBarrierAttr(),
+      targetOp.getThreadLimitNumDimsAttr(), 
targetOp.getThreadLimitDimsValues(),
       targetOp.getThreadLimit(), targetOp.getPrivateMapsAttr());
   rewriter.inlineRegionBefore(targetOp.getRegion(), newTargetOp.getRegion(),
                               newTargetOp.getRegion().begin());
@@ -1485,8 +1486,9 @@ genPreTargetOp(omp::TargetOp targetOp, SmallVector<Value> 
&preMapOperands,
       targetOp.getInReductionByrefAttr(), targetOp.getInReductionSymsAttr(),
       targetOp.getIsDevicePtrVars(), preMapOperands, targetOp.getNowaitAttr(),
       targetOp.getPrivateVars(), targetOp.getPrivateSymsAttr(),
-      targetOp.getPrivateNeedsBarrierAttr(), targetOp.getThreadLimit(),
-      targetOp.getPrivateMapsAttr());
+      targetOp.getPrivateNeedsBarrierAttr(),
+      targetOp.getThreadLimitNumDimsAttr(), 
targetOp.getThreadLimitDimsValues(),
+      targetOp.getThreadLimit(), targetOp.getPrivateMapsAttr());
   auto *preTargetBlock = rewriter.createBlock(
       &preTargetOp.getRegion(), preTargetOp.getRegion().begin(), {}, {});
   IRMapping preMapping;
@@ -1575,8 +1577,9 @@ genIsolatedTargetOp(omp::TargetOp targetOp, 
SmallVector<Value> &postMapOperands,
       targetOp.getInReductionByrefAttr(), targetOp.getInReductionSymsAttr(),
       targetOp.getIsDevicePtrVars(), postMapOperands, targetOp.getNowaitAttr(),
       targetOp.getPrivateVars(), targetOp.getPrivateSymsAttr(),
-      targetOp.getPrivateNeedsBarrierAttr(), targetOp.getThreadLimit(),
-      targetOp.getPrivateMapsAttr());
+      targetOp.getPrivateNeedsBarrierAttr(),
+      targetOp.getThreadLimitNumDimsAttr(), 
targetOp.getThreadLimitDimsValues(),
+      targetOp.getThreadLimit(), targetOp.getPrivateMapsAttr());
   auto *isolatedTargetBlock =
       rewriter.createBlock(&isolatedTargetOp.getRegion(),
                            isolatedTargetOp.getRegion().begin(), {}, {});
@@ -1655,8 +1658,9 @@ static omp::TargetOp genPostTargetOp(omp::TargetOp 
targetOp,
       targetOp.getInReductionByrefAttr(), targetOp.getInReductionSymsAttr(),
       targetOp.getIsDevicePtrVars(), postMapOperands, targetOp.getNowaitAttr(),
       targetOp.getPrivateVars(), targetOp.getPrivateSymsAttr(),
-      targetOp.getPrivateNeedsBarrierAttr(), targetOp.getThreadLimit(),
-      targetOp.getPrivateMapsAttr());
+      targetOp.getPrivateNeedsBarrierAttr(),
+      targetOp.getThreadLimitNumDimsAttr(), 
targetOp.getThreadLimitDimsValues(),
+      targetOp.getThreadLimit(), targetOp.getPrivateMapsAttr());
   // Create the block for postTargetOp
   auto *postTargetBlock = rewriter.createBlock(
       &postTargetOp.getRegion(), postTargetOp.getRegion().begin(), {}, {});
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td 
b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index e36dc7c246f01..366855bf02968 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1452,16 +1452,43 @@ class OpenMP_ThreadLimitClauseSkip<
   > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
                     extraClassDeclaration> {
   let arguments = (ins
+    ConfinedAttr<OptionalAttr<I64Attr>, [IntPositive]>:$thread_limit_num_dims,
+    Variadic<AnyInteger>:$thread_limit_dims_values,
     Optional<AnyInteger>:$thread_limit
   );
 
   let optAssemblyFormat = [{
-    `thread_limit` `(` $thread_limit `:` type($thread_limit) `)`
+    `thread_limit` `(` custom<ThreadLimitClause>(
+      $thread_limit_num_dims, $thread_limit_dims_values, 
type($thread_limit_dims_values),
+      $thread_limit, type($thread_limit)
+    ) `)`
   }];
 
   let description = [{
     The optional `thread_limit` specifies the limit on the number of threads.
   }];
+
+  let extraClassDeclaration = [{
+    /// Returns true if the dims modifier is explicitly present
+    bool hasThreadLimitDimsModifier() {
+      return getThreadLimitNumDims().has_value() && 
getThreadLimitNumDims().value();
+    }
+
+    /// Returns the number of dimensions specified by dims modifier
+    unsigned getThreadLimitDimsCount() {
+      if (!hasThreadLimitDimsModifier())
+        return 1;
+      return static_cast<unsigned>(*getThreadLimitNumDims());
+    }
+
+    /// Returns the value for a specific dimension index
+    /// Index must be less than getThreadLimitDimsCount()
+    ::mlir::Value getThreadLimitDimensionValue(unsigned index) {
+      assert(index < getThreadLimitDimsCount() &&
+             "Thread limit dims index out of bounds");
+      return getThreadLimitDimsValues()[index];
+    }
+  }];
 }
 
 def OpenMP_ThreadLimitClause : OpenMP_ThreadLimitClauseSkip<>;
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp 
b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index d4dbf5f5244df..a5348b817ab27 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2239,10 +2239,30 @@ void TargetOp::build(OpBuilder &builder, OperationState 
&state,
                   /*in_reduction_syms=*/nullptr, clauses.isDevicePtrVars,
                   clauses.mapVars, clauses.nowait, clauses.privateVars,
                   makeArrayAttr(ctx, clauses.privateSyms),
-                  clauses.privateNeedsBarrier, clauses.threadLimit,
+                  clauses.privateNeedsBarrier, clauses.threadLimitNumDims,
+                  clauses.threadLimitDimsValues, clauses.threadLimit,
                   /*private_maps=*/nullptr);
 }
 
+// helper for thread_limit clause restrictions
+static LogicalResult
+verifyThreadLimitClause(Operation *op,
+                        std::optional<IntegerAttr> threadLimitNumDims,
+                        OperandRange threadLimitDimsValues, Value threadLimit) 
{
+  bool hasDimsModifier =
+      threadLimitNumDims.has_value() && threadLimitNumDims.value();
+
+  if (hasDimsModifier && threadLimit) {
+    return op->emitError("thread_limit with dims modifier cannot be used "
+                         "together with number of threads");
+  }
+
+  if (failed(verifyDimsModifier(op, threadLimitNumDims, 
threadLimitDimsValues)))
+    return failure();
+
+  return success();
+}
+
 LogicalResult TargetOp::verify() {
   if (failed(verifyDependVarList(*this, getDependKinds(), getDependVars())))
     return failure();
@@ -2254,6 +2274,11 @@ LogicalResult TargetOp::verify() {
   if (failed(verifyMapClause(*this, getMapVars())))
     return failure();
 
+  if (failed(verifyThreadLimitClause(*this, getThreadLimitNumDimsAttr(),
+                                     getThreadLimitDimsValues(),
+                                     getThreadLimit())))
+    return failure();
+
   return verifyPrivateVarsMapping(*this);
 }
 
@@ -2661,7 +2686,8 @@ void TeamsOp::build(OpBuilder &builder, OperationState 
&state,
       /*private_needs_barrier=*/nullptr, clauses.reductionMod,
       clauses.reductionVars,
       makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
-      makeArrayAttr(ctx, clauses.reductionSyms), clauses.threadLimit);
+      makeArrayAttr(ctx, clauses.reductionSyms), clauses.threadLimitNumDims,
+      clauses.threadLimitDimsValues, clauses.threadLimit);
 }
 
 // Helper: Verify num_teams clause
@@ -2721,6 +2747,12 @@ LogicalResult TeamsOp::verify() {
     return emitError(
         "expected equal sizes for allocate and allocator variables");
 
+  // Check for thread_limit clause restrictions
+  if (failed(verifyThreadLimitClause(*this, getThreadLimitNumDimsAttr(),
+                                     getThreadLimitDimsValues(),
+                                     getThreadLimit())))
+    return failure();
+
   return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
                                 getReductionByref());
 }
@@ -4647,6 +4679,42 @@ static void printNumTeamsClause(OpAsmPrinter &p, 
Operation *op,
   }
 }
 
+//===----------------------------------------------------------------------===//
+// Parser and printer for thread_limit clause
+//===----------------------------------------------------------------------===//
+static ParseResult
+parseThreadLimitClause(OpAsmParser &parser, IntegerAttr &dimsAttr,
+                       SmallVectorImpl<OpAsmParser::UnresolvedOperand> &values,
+                       SmallVectorImpl<Type> &types,
+                       std::optional<OpAsmParser::UnresolvedOperand> &bounds,
+                       Type &boundsType) {
+  if (succeeded(parseDimsModifierWithValues(parser, dimsAttr, values, types))) 
{
+    return success();
+  }
+
+  OpAsmParser::UnresolvedOperand boundsOperand;
+  if (parser.parseOperand(boundsOperand) || parser.parseColon() ||
+      parser.parseType(boundsType)) {
+    return failure();
+  }
+  bounds = boundsOperand;
+  return success();
+}
+
+static void printThreadLimitClause(OpAsmPrinter &p, Operation *op,
+                                   IntegerAttr dimsAttr, OperandRange values,
+                                   TypeRange types, Value bounds,
+                                   Type boundsType) {
+  if (!values.empty()) {
+    // Multidimensional: dims(N): values : type
+    printDimsModifierWithValues(p, dimsAttr, values, types);
+  } else if (bounds) {
+    // Both bounds: bounds : type
+    p.printOperand(bounds);
+    p << " : " << boundsType;
+  }
+}
+
 #define GET_ATTRDEF_CLASSES
 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
 
diff --git 
a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp 
b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 00f782e87d5af..b4cc0802d166f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -1985,6 +1985,10 @@ convertOmpTeams(omp::TeamsOp op, llvm::IRBuilderBase 
&builder,
     return op.emitError("Lowering of num_teams with dims modifier is NYI.");
   }
 
+  if (op.hasThreadLimitDimsModifier()) {
+    return op.emitError("Lowering of thread_limit with dims modifier is NYI.");
+  }
+
   DenseMap<Value, llvm::Value *> reductionVariableMap;
   unsigned numReductionVars = op.getNumReductionVars();
   SmallVector<omp::DeclareReductionOp> reductionDecls;
@@ -5594,6 +5598,8 @@ extractHostEvalClauses(omp::TargetOp targetOp, Value 
&numThreads,
             // num_teams dims and values are not yet supported
             assert(!teamsOp.hasNumTeamsDimsModifier() &&
                    "Lowering of num_teams with dims modifier is NYI.");
+            assert(!teamsOp.hasThreadLimitDimsModifier() &&
+                   "Lowering of thread_limit with dims modifier is NYI.");
             if (teamsOp.getNumTeamsLower() == blockArg)
               numTeamsLower = hostEvalVar;
             else if (teamsOp.getNumTeamsUpper() == blockArg)
@@ -5719,6 +5725,8 @@ initTargetDefaultAttrs(omp::TargetOp targetOp, Operation 
*capturedOp,
       // num_teams dims and values are not yet supported
       assert(!teamsOp.hasNumTeamsDimsModifier() &&
              "Lowering of num_teams with dims modifier is NYI.");
+      assert(!teamsOp.hasThreadLimitDimsModifier() &&
+             "Lowering of thread_limit with dims modifier is NYI.");
       numTeamsLower = teamsOp.getNumTeamsLower();
       numTeamsUpper = teamsOp.getNumTeamsUpper();
       threadLimit = teamsOp.getThreadLimit();
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir 
b/mlir/test/Dialect/OpenMP/invalid.mlir
index dd367aba8da27..7f69ca5aaa064 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -1438,7 +1438,7 @@ func.func @omp_teams_allocate(%data_var : memref<i32>) {
     // expected-error @below {{expected equal sizes for allocate and allocator 
variables}}
     "omp.teams" (%data_var) ({
       omp.terminator
-    }) {operandSegmentSizes = array<i32: 1,0,0,0,0,0,0,0,0>} : (memref<i32>) 
-> ()
+    }) {operandSegmentSizes = array<i32: 1,0,0,0,0,0,0,0,0,0>} : (memref<i32>) 
-> ()
     omp.terminator
   }
   return
@@ -1451,7 +1451,7 @@ func.func @omp_teams_num_teams1(%lb : i32) {
     // expected-error @below {{expected num_teams upper bound to be defined if 
the lower bound is defined}}
     "omp.teams" (%lb) ({
       omp.terminator
-    }) {operandSegmentSizes = array<i32: 0,0,0,0,1,0,0,0,0>} : (i32) -> ()
+    }) {operandSegmentSizes = array<i32: 0,0,0,0,1,0,0,0,0,0>} : (i32) -> ()
     omp.terminator
   }
   return
@@ -1466,7 +1466,7 @@ func.func @omp_teams_num_teams_dims_mismatch() {
     // expected-error @below {{dims(3) specified but 2 values provided}}
     "omp.teams" (%v0, %v1) ({
       omp.terminator
-    }) {num_teams_num_dims = 3 : i64, operandSegmentSizes = array<i32: 
0,0,0,2,0,0,0,0,0>} : (i32, i32) -> ()
+    }) {num_teams_num_dims = 3 : i64, operandSegmentSizes = array<i32: 
0,0,0,2,0,0,0,0,0,0>} : (i32, i32) -> ()
     omp.terminator
   }
   return
@@ -1483,7 +1483,7 @@ func.func @omp_teams_num_teams_dims_with_bounds() {
     // expected-error @below {{num_teams with dims modifier cannot be used 
together with lower/upper bounds}}
     "omp.teams" (%v0, %v1, %lb, %ub) ({
       omp.terminator
-    }) {num_teams_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,2,1,1,0,0,0>} : (i32, i32, i32, i32) -> ()
+    }) {num_teams_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,2,1,1,0,0,0,0>} : (i32, i32, i32, i32) -> ()
     omp.terminator
   }
   return
@@ -1498,7 +1498,7 @@ func.func @omp_teams_num_teams_values_without_dims() {
     // expected-error @below {{dims values can only be specified with dims 
modifier}}
     "omp.teams" (%v0, %v1) ({
       omp.terminator
-    }) {operandSegmentSizes = array<i32: 0,0,0,2,0,0,0,0,0>} : (i32, i32) -> ()
+    }) {operandSegmentSizes = array<i32: 0,0,0,2,0,0,0,0,0,0>} : (i32, i32) -> 
()
     omp.terminator
   }
   return
@@ -1511,7 +1511,7 @@ func.func @omp_teams_num_teams_dims_no_values() {
     // expected-error @below {{dims modifier requires values to be specified}}
     "omp.teams" () ({
       omp.terminator
-    }) {num_teams_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,0>} : () -> ()
+    }) {num_teams_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,0,0>} : () -> ()
     omp.terminator
   }
   return
@@ -1526,7 +1526,7 @@ func.func @omp_teams_num_teams_dims_type_mismatch() {
     // expected-error @below {{dims modifier requires all values to have the 
same type}}
     "omp.teams" (%v0, %v1) ({
       omp.terminator
-    }) {num_teams_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,2,0,0,0,0,0>} : (i32, i64) -> ()
+    }) {num_teams_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,2,0,0,0,0,0,0>} : (i32, i64) -> ()
     omp.terminator
   }
   return
@@ -1547,6 +1547,139 @@ func.func @omp_teams_num_teams2(%lb : i32, %ub : i16) {
 
 // -----
 
+func.func @omp_teams_thread_limit_dims_mismatch() {
+  omp.target {
+    %v0 = arith.constant 1 : i32
+    %v1 = arith.constant 2 : i32
+    // expected-error @below {{dims(3) specified but 2 values provided}}
+    "omp.teams" (%v0, %v1) ({
+      omp.terminator
+    }) {thread_limit_num_dims = 3 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,2,0>} : (i32, i32) -> ()
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+func.func @omp_teams_thread_limit_dims_with_scalar() {
+  omp.target {
+    %v0 = arith.constant 1 : i32
+    %v1 = arith.constant 2 : i32
+    %tl = arith.constant 4 : i32
+    // expected-error @below {{thread_limit with dims modifier cannot be used 
together with number of threads}}
+    "omp.teams" (%v0, %v1, %tl) ({
+      omp.terminator
+    }) {thread_limit_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,2,1>} : (i32, i32, i32) -> ()
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+func.func @omp_teams_thread_limit_dims_no_values() {
+  omp.target {
+    // expected-error @below {{dims modifier requires values to be specified}}
+    "omp.teams" () ({
+      omp.terminator
+    }) {thread_limit_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,0>} : () -> ()
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+func.func @omp_teams_thread_limit_values_without_dims() {
+  omp.target {
+    %v0 = arith.constant 1 : i32
+    %v1 = arith.constant 2 : i32
+    // expected-error @below {{dims values can only be specified with dims 
modifier}}
+    "omp.teams" (%v0, %v1) ({
+      omp.terminator
+    }) {operandSegmentSizes = array<i32: 0,0,0,0,0,0,0,0,2,0>} : (i32, i32) -> 
()
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+func.func @omp_teams_thread_limit_dims_type_mismatch() {
+  omp.target {
+    %v0 = arith.constant 1 : i32
+    %v1 = arith.constant 2 : i64
+    // expected-error @below {{dims modifier requires all values to have the 
same type}}
+    "omp.teams" (%v0, %v1) ({
+      omp.terminator
+    }) {thread_limit_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,2,0>} : (i32, i64) -> ()
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+func.func @omp_target_thread_limit_dims_mismatch() {
+  %v0 = arith.constant 1 : i32
+  %v1 = arith.constant 2 : i32
+  // expected-error @below {{dims(3) specified but 2 values provided}}
+  "omp.target" (%v0, %v1) ({
+    omp.terminator
+  }) {thread_limit_num_dims = 3 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,0,0,0,2,0>} : (i32, i32) -> ()
+  return
+}
+
+// -----
+
+func.func @omp_target_thread_limit_dims_with_scalar() {
+  %v0 = arith.constant 1 : i32
+  %v1 = arith.constant 2 : i32
+  %tl = arith.constant 4 : i32
+  // expected-error @below {{thread_limit with dims modifier cannot be used 
together with number of threads}}
+  "omp.target" (%v0, %v1, %tl) ({
+    omp.terminator
+  }) {thread_limit_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,0,0,0,2,1>} : (i32, i32, i32) -> ()
+  return
+}
+
+// -----
+
+func.func @omp_target_thread_limit_dims_no_values() {
+  // expected-error @below {{dims modifier requires values to be specified}}
+  "omp.target" () ({
+    omp.terminator
+  }) {thread_limit_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,0,0,0,0,0>} : () -> ()
+  return
+}
+
+// -----
+
+func.func @omp_target_thread_limit_values_without_dims() {
+  %v0 = arith.constant 1 : i32
+  %v1 = arith.constant 2 : i32
+  // expected-error @below {{dims values can only be specified with dims 
modifier}}
+  "omp.target" (%v0, %v1) ({
+    omp.terminator
+  }) {operandSegmentSizes = array<i32: 0,0,0,0,0,0,0,0,0,0,0,2,0>} : (i32, 
i32) -> ()
+  return
+}
+
+// -----
+
+func.func @omp_target_thread_limit_dims_type_mismatch() {
+  %v0 = arith.constant 1 : i32
+  %v1 = arith.constant 2 : i64
+  // expected-error @below {{dims modifier requires all values to have the 
same type}}
+  "omp.target" (%v0, %v1) ({
+    omp.terminator
+  }) {thread_limit_num_dims = 2 : i64, operandSegmentSizes = array<i32: 
0,0,0,0,0,0,0,0,0,0,0,2,0>} : (i32, i64) -> ()
+  return
+}
+
+// -----
+
 func.func @omp_sections(%data_var : memref<i32>) -> () {
   // expected-error @below {{expected equal sizes for allocate and allocator 
variables}}
   "omp.sections" (%data_var) ({
@@ -2533,7 +2666,7 @@ func.func @omp_target_depend(%data_var: memref<i32>) {
   // expected-error @below {{op expected as many depend values as depend 
variables}}
     "omp.target"(%data_var) ({
       "omp.terminator"() : () -> ()
-    }) {depend_kinds = [], operandSegmentSizes = array<i32: 0, 0, 1, 0, 0, 0, 
0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
+    }) {depend_kinds = [], operandSegmentSizes = array<i32: 0, 0, 1, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
    "func.return"() : () -> ()
 }
 
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir 
b/mlir/test/Dialect/OpenMP/ops.mlir
index 3633a4be1eb62..a1146fbb263e6 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -823,7 +823,7 @@ func.func @omp_target(%if_cond : i1, %device : si32,  
%num_threads : i32, %devic
     "omp.target"(%device, %if_cond, %num_threads) ({
        // CHECK: omp.terminator
        omp.terminator
-    }) {nowait, operandSegmentSizes = array<i32: 0,0,0,1,0,0,1,0,0,0,0,1>} : ( 
si32, i1, i32 ) -> ()
+    }) {nowait, operandSegmentSizes = array<i32: 0,0,0,1,0,0,1,0,0,0,0,0,1>} : 
( si32, i1, i32 ) -> ()
 
     // Test with optional map clause.
     // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : 
memref<?xi32>, tensor<?xi32>)   map_clauses(always, to) capture(ByRef) -> 
memref<?xi32> {name = ""}
@@ -1128,6 +1128,12 @@ func.func @omp_teams(%lb : i32, %ub : i32, %if_cond : 
i1, %num_threads : i32,
     omp.terminator
   }
 
+  // CHECK: omp.teams thread_limit(dims(2): %{{.*}}, %{{.*}} : i32)
+  omp.teams thread_limit(dims(2): %lb, %ub : i32) {
+    // CHECK: omp.terminator
+    omp.terminator
+  }
+
   // Test reduction.
   %c1 = arith.constant 1 : i32
   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr

>From 67b209b82303f1b7133c7458193377cd27e52781 Mon Sep 17 00:00:00 2001
From: skc7 <[email protected]>
Date: Thu, 11 Dec 2025 18:35:55 +0530
Subject: [PATCH 2/2] update thread_limit description

---
 mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td 
b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 366855bf02968..4a0d1fd0af02c 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1465,7 +1465,18 @@ class OpenMP_ThreadLimitClauseSkip<
   }];
 
   let description = [{
-    The optional `thread_limit` specifies the limit on the number of threads.
+    The `thread_limit` clause specifies the limit on the number of threads.
+
+    With dims modifier:
+    - The number of dimensions is specified by the `thread_limit_num_dims` 
attribute.
+    - The values for each dimension are specified by the 
`thread_limit_dims_values` attribute.
+    - Format: `thread_limit(dims(N): values : type)`
+    - Example: `thread_limit(dims(2): %n, %m : i64)`
+
+    Without dims modifier:
+    - The number of threads is specified by the `thread_limit`.
+    - Format: `thread_limit(number_of_threads : type)`
+    - Example: `thread_limit(%n : i64)`
   }];
 
   let extraClassDeclaration = [{

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to