[Mlir-commits] [mlir] [OpenMP][mlir] Add DynGroupPrivateClause in omp dialect (PR #153562)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Aug 18 05:23:09 PDT 2025


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

>From e84c851002741e9e65c9e08398a87df4e54de629 Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Thu, 14 Aug 2025 09:46:31 +0530
Subject: [PATCH 1/5] [OpenMP][mlir] Add DynGroupPrivateClause in omp dialect

---
 .../mlir/Dialect/OpenMP/OpenMPClauses.td      | 43 +++++++++++++++++++
 .../mlir/Dialect/OpenMP/OpenMPEnums.td        | 22 ++++++++++
 2 files changed, 65 insertions(+)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 311c57fb4446c..424a490838ae5 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1470,4 +1470,47 @@ class OpenMP_UseDevicePtrClauseSkip<
 
 def OpenMP_UseDevicePtrClause : OpenMP_UseDevicePtrClauseSkip<>;
 
+//===----------------------------------------------------------------------===//
+// V6.1 `dyn_groupprivate` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_DynGroupPrivateClauseSkip<
+    bit traits = false, bit arguments = false, bit assemblyFormat = false,
+    bit description = false, bit extraClassDeclaration = false
+  > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+                    extraClassDeclaration> {
+
+  let arguments = (ins
+    DynGroupPrivateModifierAttr:$modifier_first,
+    DynGroupPrivateModifierAttr:$modifier_second,
+    AnyInteger:$size
+  );
+
+  let description = [{
+    The `dyn_groupprivate` clause allows you to dynamically allocate group-private
+    memory in OpenMP parallel regions, specifically for `target` and `teams` directives.
+    This clause enables runtime-sized private memory allocation and applicable to
+    target and teams ops.
+
+    Syntax:
+    ```
+    dyn_groupprivate(modifier_first ,modifier_second : size)
+    ```
+
+    Example:
+    ```
+    omp.target dyn_groupprivate(strict, cgroup : %size : i32)
+    ```
+  }];
+
+  let optAssemblyFormat = [{
+  `dyn_groupprivate` `(`
+    $modifier_first `,` $modifier_second
+    `:` $size `:` type($size)
+  `)`
+  }];
+}
+
+def OpenMP_DynGroupPrivateClause : OpenMP_DynGroupPrivateClauseSkip<>;
+
 #endif // OPENMP_CLAUSES
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
index c080c3fac87d4..81531dd0baf7b 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
@@ -293,4 +293,26 @@ def AllocatorHandle : OpenMP_I32EnumAttr<
     ]>;
 
 def AllocatorHandleAttr : OpenMP_EnumAttr<AllocatorHandle, "allocator_handle">;
+
+//===----------------------------------------------------------------------===//
+// dyn_groupprivate enum.
+//===----------------------------------------------------------------------===//
+
+def DynGroupPrivateCGroup : I32EnumAttrCase<"cgroup", 0>;
+def DynGroupPrivateStrict : I32EnumAttrCase<"strict", 1>;
+def DynGroupPrivateFallback : I32EnumAttrCase<"fallback", 2>;
+
+def DynGroupPrivateModifier : OpenMP_I32EnumAttr<
+    "DynGroupPrivateModifier",
+    "reduction modifier", [
+      DynGroupPrivateCGroup,
+      DynGroupPrivateStrict,
+      DynGroupPrivateFallback
+    ]>;
+
+def DynGroupPrivateModifierAttr : OpenMP_EnumAttr<DynGroupPrivateModifier,
+                                            "dyn_groupprivate_modifier"> {
+  let assemblyFormat = "`(` $value `)`";
+}
+
 #endif // OPENMP_ENUMS

>From 772c11000bbc85e3b23d3d8d3ecab1040ae3339c Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Thu, 14 Aug 2025 15:36:11 +0530
Subject: [PATCH 2/5] Add dyn_groupprivate clause to teams and target ops

---
 .../mlir/Dialect/OpenMP/OpenMPClauses.td      | 19 ++++++++++---------
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |  5 +++--
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  5 ++++-
 3 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 424a490838ae5..a0ac73f5311e0 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1481,9 +1481,9 @@ class OpenMP_DynGroupPrivateClauseSkip<
                     extraClassDeclaration> {
 
   let arguments = (ins
-    DynGroupPrivateModifierAttr:$modifier_first,
-    DynGroupPrivateModifierAttr:$modifier_second,
-    AnyInteger:$size
+    OptionalAttr<DynGroupPrivateModifierAttr>:$modifier_first,
+    OptionalAttr<DynGroupPrivateModifierAttr>:$modifier_second,
+    Optional<AnyInteger>:$dyn_groupprivate_size
   );
 
   let description = [{
@@ -1494,20 +1494,21 @@ class OpenMP_DynGroupPrivateClauseSkip<
 
     Syntax:
     ```
-    dyn_groupprivate(modifier_first ,modifier_second : size)
+    dyn_groupprivate(modifier_first ,modifier_second : dyn_groupprivate_size)
     ```
 
     Example:
     ```
-    omp.target dyn_groupprivate(strict, cgroup : %size : i32)
+    omp.target dyn_groupprivate(strict, cgroup : %dyn_groupprivate_size : i32)
     ```
   }];
 
   let optAssemblyFormat = [{
-  `dyn_groupprivate` `(`
-    $modifier_first `,` $modifier_second
-    `:` $size `:` type($size)
-  `)`
+    `dyn_groupprivate` `(`
+      ($modifier_first^)?
+      (`,` $modifier_second^)?
+      (`:` $dyn_groupprivate_size^ `:` type($dyn_groupprivate_size))?
+    `)`
   }];
 }
 
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index be114ea4fb631..c5ee82d245d67 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -241,7 +241,8 @@ def TeamsOp : OpenMP_Op<"teams", traits = [
     AttrSizedOperandSegments, RecursiveMemoryEffects, OutlineableOpenMPOpInterface
   ], clauses = [
     OpenMP_AllocateClause, OpenMP_IfClause, OpenMP_NumTeamsClause,
-    OpenMP_PrivateClause, OpenMP_ReductionClause, OpenMP_ThreadLimitClause
+    OpenMP_PrivateClause, OpenMP_ReductionClause, OpenMP_ThreadLimitClause,
+    OpenMP_DynGroupPrivateClause
   ], singleRegion = true> {
   let summary = "teams construct";
   let description = [{
@@ -1464,7 +1465,7 @@ def TargetOp : OpenMP_Op<"target", traits = [
     OpenMP_DeviceClause, OpenMP_HasDeviceAddrClause, OpenMP_HostEvalClause,
     OpenMP_IfClause, OpenMP_InReductionClause, OpenMP_IsDevicePtrClause,
     OpenMP_MapClauseSkip<assemblyFormat = true>, OpenMP_NowaitClause,
-    OpenMP_PrivateClause, OpenMP_ThreadLimitClause
+    OpenMP_PrivateClause, OpenMP_ThreadLimitClause, OpenMP_DynGroupPrivateClause
   ], singleRegion = true> {
   let summary = "target construct";
   let description = [{
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index c1c1767ef90b0..1dfca0231b945 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -1951,6 +1951,8 @@ void TargetOp::build(OpBuilder &builder, OperationState &state,
                   clauses.mapVars, clauses.nowait, clauses.privateVars,
                   makeArrayAttr(ctx, clauses.privateSyms),
                   clauses.privateNeedsBarrier, clauses.threadLimit,
+                  clauses.modifierFirst, clauses.modifierSecond,
+                  clauses.dynGroupprivateSize,
                   /*private_maps=*/nullptr);
 }
 
@@ -2340,7 +2342,8 @@ void TeamsOp::build(OpBuilder &builder, OperationState &state,
                  clauses.reductionVars,
                  makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
                  makeArrayAttr(ctx, clauses.reductionSyms),
-                 clauses.threadLimit);
+                 clauses.threadLimit, clauses.modifierFirst,
+                 clauses.modifierSecond, clauses.dynGroupprivateSize);
 }
 
 LogicalResult TeamsOp::verify() {

>From ae00e078a8b2288f0e05bd659653206f1a241022 Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Sun, 17 Aug 2025 12:07:13 +0530
Subject: [PATCH 3/5] Fix clause name and tests

---
 .../mlir/Dialect/OpenMP/OpenMPClauses.td       |  8 ++++----
 .../include/mlir/Dialect/OpenMP/OpenMPEnums.td | 18 +++++++++---------
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td  |  4 ++--
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp   |  6 +++---
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp       |  6 ++++++
 mlir/test/Dialect/OpenMP/invalid.mlir          |  6 +++---
 mlir/test/Dialect/OpenMP/ops.mlir              |  2 +-
 7 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index a0ac73f5311e0..bb7fbd2287f40 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1474,15 +1474,15 @@ def OpenMP_UseDevicePtrClause : OpenMP_UseDevicePtrClauseSkip<>;
 // V6.1 `dyn_groupprivate` clause
 //===----------------------------------------------------------------------===//
 
-class OpenMP_DynGroupPrivateClauseSkip<
+class OpenMP_DynGroupprivateClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false
   > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
                     extraClassDeclaration> {
 
   let arguments = (ins
-    OptionalAttr<DynGroupPrivateModifierAttr>:$modifier_first,
-    OptionalAttr<DynGroupPrivateModifierAttr>:$modifier_second,
+    OptionalAttr<DynGroupprivateModifierAttr>:$modifier_first,
+    OptionalAttr<DynGroupprivateModifierAttr>:$modifier_second,
     Optional<AnyInteger>:$dyn_groupprivate_size
   );
 
@@ -1512,6 +1512,6 @@ class OpenMP_DynGroupPrivateClauseSkip<
   }];
 }
 
-def OpenMP_DynGroupPrivateClause : OpenMP_DynGroupPrivateClauseSkip<>;
+def OpenMP_DynGroupprivateClause : OpenMP_DynGroupprivateClauseSkip<>;
 
 #endif // OPENMP_CLAUSES
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
index 81531dd0baf7b..19a7b3dbbc759 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
@@ -298,19 +298,19 @@ def AllocatorHandleAttr : OpenMP_EnumAttr<AllocatorHandle, "allocator_handle">;
 // dyn_groupprivate enum.
 //===----------------------------------------------------------------------===//
 
-def DynGroupPrivateCGroup : I32EnumAttrCase<"cgroup", 0>;
-def DynGroupPrivateStrict : I32EnumAttrCase<"strict", 1>;
-def DynGroupPrivateFallback : I32EnumAttrCase<"fallback", 2>;
+def DynGroupprivateCGroup : I32EnumAttrCase<"cgroup", 0>;
+def DynGroupprivateStrict : I32EnumAttrCase<"strict", 1>;
+def DynGroupprivateFallback : I32EnumAttrCase<"fallback", 2>;
 
-def DynGroupPrivateModifier : OpenMP_I32EnumAttr<
-    "DynGroupPrivateModifier",
+def DynGroupprivateModifier : OpenMP_I32EnumAttr<
+    "DynGroupprivateModifier",
     "reduction modifier", [
-      DynGroupPrivateCGroup,
-      DynGroupPrivateStrict,
-      DynGroupPrivateFallback
+      DynGroupprivateCGroup,
+      DynGroupprivateStrict,
+      DynGroupprivateFallback
     ]>;
 
-def DynGroupPrivateModifierAttr : OpenMP_EnumAttr<DynGroupPrivateModifier,
+def DynGroupprivateModifierAttr : OpenMP_EnumAttr<DynGroupprivateModifier,
                                             "dyn_groupprivate_modifier"> {
   let assemblyFormat = "`(` $value `)`";
 }
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index c5ee82d245d67..315233102be47 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -242,7 +242,7 @@ def TeamsOp : OpenMP_Op<"teams", traits = [
   ], clauses = [
     OpenMP_AllocateClause, OpenMP_IfClause, OpenMP_NumTeamsClause,
     OpenMP_PrivateClause, OpenMP_ReductionClause, OpenMP_ThreadLimitClause,
-    OpenMP_DynGroupPrivateClause
+    OpenMP_DynGroupprivateClause
   ], singleRegion = true> {
   let summary = "teams construct";
   let description = [{
@@ -1465,7 +1465,7 @@ def TargetOp : OpenMP_Op<"target", traits = [
     OpenMP_DeviceClause, OpenMP_HasDeviceAddrClause, OpenMP_HostEvalClause,
     OpenMP_IfClause, OpenMP_InReductionClause, OpenMP_IsDevicePtrClause,
     OpenMP_MapClauseSkip<assemblyFormat = true>, OpenMP_NowaitClause,
-    OpenMP_PrivateClause, OpenMP_ThreadLimitClause, OpenMP_DynGroupPrivateClause
+    OpenMP_PrivateClause, OpenMP_ThreadLimitClause, OpenMP_DynGroupprivateClause
   ], singleRegion = true> {
   let summary = "target construct";
   let description = [{
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 1dfca0231b945..0867123e07552 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2341,9 +2341,9 @@ 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, clauses.modifierFirst,
-                 clauses.modifierSecond, clauses.dynGroupprivateSize);
+                 makeArrayAttr(ctx, clauses.reductionSyms), clauses.threadLimit,
+                 clauses.modifierFirst, clauses.modifierSecond,
+                 clauses.dynGroupprivateSize);
 }
 
 LogicalResult TeamsOp::verify() {
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index eb96cb211fdd5..a25098d22a8f3 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -383,6 +383,10 @@ static LogicalResult checkImplementationStatus(Operation &op) {
     if (op.getUntied())
       result = todo("untied");
   };
+  auto checkDynGroupprivate = [&todo](auto op, LogicalResult &result) {
+    if (op.getDynGroupprivateSize())
+      result = todo("dyn_groupprivate");
+  };
 
   LogicalResult result = success();
   llvm::TypeSwitch<Operation &>(op)
@@ -408,6 +412,7 @@ static LogicalResult checkImplementationStatus(Operation &op) {
       .Case([&](omp::TeamsOp op) {
         checkAllocate(op, result);
         checkPrivate(op, result);
+        checkDynGroupprivate(op, result);
       })
       .Case([&](omp::TaskOp op) {
         checkAllocate(op, result);
@@ -451,6 +456,7 @@ static LogicalResult checkImplementationStatus(Operation &op) {
         checkInReduction(op, result);
         checkIsDevicePtr(op, result);
         checkPrivate(op, result);
+        checkDynGroupprivate(op, result);
       })
       .Default([](Operation &) {
         // Assume all clauses for an operation can be translated unless they are
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 5088f2dfa7d7a..7efc5258f4c23 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -1415,7 +1415,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>} : (memref<i32>) -> ()
+    }) {operandSegmentSizes = array<i32: 1,0,0,0,0,0,0,0,0>} : (memref<i32>) -> ()
     omp.terminator
   }
   return
@@ -1428,7 +1428,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,1,0,0,0,0>} : (i32) -> ()
+    }) {operandSegmentSizes = array<i32: 0,0,0,1,0,0,0,0,0>} : (i32) -> ()
     omp.terminator
   }
   return
@@ -2435,7 +2435,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 8c846cde1a3ca..9dbadb219fadb 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -769,7 +769,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,1,0>} : ( 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 = ""}

>From 86811e7b63809dc859b4358a7a846dbb3bf17c0e Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Mon, 18 Aug 2025 17:32:16 +0530
Subject: [PATCH 4/5] Add parser printer and verify for dyn_groupprivate clause

---
 .../mlir/Dialect/OpenMP/OpenMPClauses.td      |   5 +-
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  | 173 ++++++++++++++++++
 mlir/test/Dialect/OpenMP/invalid.mlir         |  34 ++++
 mlir/test/Dialect/OpenMP/ops.mlir             |  31 +++-
 4 files changed, 239 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index bb7fbd2287f40..3c55b860d8a42 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1505,9 +1505,8 @@ class OpenMP_DynGroupprivateClauseSkip<
 
   let optAssemblyFormat = [{
     `dyn_groupprivate` `(`
-      ($modifier_first^)?
-      (`,` $modifier_second^)?
-      (`:` $dyn_groupprivate_size^ `:` type($dyn_groupprivate_size))?
+      custom<DynGroupprivateClause>($modifier_first, $modifier_second, 
+      $dyn_groupprivate_size, type($dyn_groupprivate_size))
     `)`
   }];
 }
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 0867123e07552..b70dbb7987208 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -566,6 +566,167 @@ static void printNumTasksClause(OpAsmPrinter &p, Operation *op,
       p, op, numTasksMod, numTasks, numTasksType, &stringifyClauseNumTasksType);
 }
 
+//===----------------------------------------------------------------------===//
+// Parser, printer and verify for dyn_groupprivate Clause
+//===----------------------------------------------------------------------===//
+
+static LogicalResult verifyDynGroupprivateClause(
+    Operation *op, DynGroupprivateModifierAttr modifierFirst,
+    DynGroupprivateModifierAttr modifierSecond, Value dynGroupprivateSize) {
+
+  // Helper to get modifier name as string
+  auto getModifierName = [](DynGroupprivateModifier mod) -> StringRef {
+    switch (mod) {
+    case DynGroupprivateModifier::strict:
+      return "strict";
+    case DynGroupprivateModifier::cgroup:
+      return "cgroup";
+    case DynGroupprivateModifier::fallback:
+      return "fallback";
+    }
+    return "unknown";
+  };
+
+  // Check for duplicate modifiers
+  if (modifierFirst && modifierSecond &&
+      modifierFirst.getValue() == modifierSecond.getValue()) {
+    return op->emitOpError("duplicate dyn_groupprivate modifier '")
+           << getModifierName(modifierFirst.getValue()) << "'";
+  }
+
+  // Check for incompatible modifier combinations
+  if (modifierFirst && modifierSecond) {
+    auto m1 = modifierFirst.getValue();
+    auto m2 = modifierSecond.getValue();
+
+    // strict and fallback are incompatible
+    if ((m1 == DynGroupprivateModifier::strict &&
+         m2 == DynGroupprivateModifier::fallback) ||
+        (m1 == DynGroupprivateModifier::fallback &&
+         m2 == DynGroupprivateModifier::strict)) {
+      return op->emitOpError("incompatible dyn_groupprivate modifiers: '")
+             << getModifierName(m1) << "' and '" << getModifierName(m2)
+             << "' cannot be used together";
+    }
+  }
+
+  // Verify the size
+  if (dynGroupprivateSize) {
+    Type size_type = dynGroupprivateSize.getType();
+    // Check if the size type is an integer type
+    if (!size_type.isIntOrIndex()) {
+      return op->emitOpError(
+                 "dyn_groupprivate size must be an integer type, got ")
+             << size_type;
+    }
+  }
+
+  return success();
+}
+
+static ParseResult parseDynGroupprivateClause(
+    OpAsmParser &parser, DynGroupprivateModifierAttr &modifierFirst,
+    DynGroupprivateModifierAttr &modifierSecond,
+    std::optional<OpAsmParser::UnresolvedOperand> &dynGroupprivateSize,
+    Type &size_type) {
+
+  bool hasModifiers = false;
+
+  // Parse first modifier if present
+  if (succeeded(parser.parseOptionalKeyword("strict"))) {
+    modifierFirst = DynGroupprivateModifierAttr::get(
+        parser.getContext(), DynGroupprivateModifier::strict);
+    hasModifiers = true;
+  } else if (succeeded(parser.parseOptionalKeyword("cgroup"))) {
+    modifierFirst = DynGroupprivateModifierAttr::get(
+        parser.getContext(), DynGroupprivateModifier::cgroup);
+    hasModifiers = true;
+  } else if (succeeded(parser.parseOptionalKeyword("fallback"))) {
+    modifierFirst = DynGroupprivateModifierAttr::get(
+        parser.getContext(), DynGroupprivateModifier::fallback);
+    hasModifiers = true;
+  }
+
+  // If first modifier found, check for comma and second modifier
+  if (hasModifiers && succeeded(parser.parseOptionalComma())) {
+    if (succeeded(parser.parseOptionalKeyword("strict"))) {
+      modifierSecond = DynGroupprivateModifierAttr::get(
+          parser.getContext(), DynGroupprivateModifier::strict);
+    } else if (succeeded(parser.parseOptionalKeyword("cgroup"))) {
+      modifierSecond = DynGroupprivateModifierAttr::get(
+          parser.getContext(), DynGroupprivateModifier::cgroup);
+    } else if (succeeded(parser.parseOptionalKeyword("fallback"))) {
+      modifierSecond = DynGroupprivateModifierAttr::get(
+          parser.getContext(), DynGroupprivateModifier::fallback);
+    } else {
+      return parser.emitError(parser.getCurrentLocation(),
+                              "expected modifier after comma");
+    }
+  }
+
+  // Parse colon and size if modifiers were present, or just try to parse
+  // operand
+  if (hasModifiers) {
+    // Modifiers present, expect colon
+    if (failed(parser.parseColon())) {
+      return parser.emitError(parser.getCurrentLocation(),
+                              "expected ':' after modifiers");
+    }
+
+    // Parse operand and type
+    OpAsmParser::UnresolvedOperand operand;
+    if (succeeded(parser.parseOperand(operand))) {
+      dynGroupprivateSize = operand;
+      if (failed(parser.parseColon()) || failed(parser.parseType(size_type))) {
+        return parser.emitError(parser.getCurrentLocation(),
+                                "expected ':' and type after size operand");
+      }
+    }
+  } else {
+    // No modifiers, try to parse operand directly
+    OpAsmParser::UnresolvedOperand operand;
+    if (succeeded(parser.parseOperand(operand))) {
+      dynGroupprivateSize = operand;
+      if (failed(parser.parseColon()) || failed(parser.parseType(size_type))) {
+        return parser.emitError(parser.getCurrentLocation(),
+                                "expected ':' and type after size operand");
+      }
+    } else {
+      return parser.emitError(parser.getCurrentLocation(),
+                              "expected dyn_groupprivate_size operand");
+    }
+  }
+
+  return success();
+}
+
+static void
+printDynGroupprivateClause(OpAsmPrinter &printer, Operation *op,
+                           DynGroupprivateModifierAttr modifierFirst,
+                           DynGroupprivateModifierAttr modifierSecond,
+                           Value dynGroupprivateSize, Type size_type) {
+
+  bool needsComma = false;
+
+  if (modifierFirst) {
+    printer << modifierFirst.getValue();
+    needsComma = true;
+  }
+
+  if (modifierSecond) {
+    if (needsComma)
+      printer << ", ";
+    printer << modifierSecond.getValue();
+    needsComma = true;
+  }
+
+  if (dynGroupprivateSize) {
+    if (needsComma)
+      printer << " : ";
+    printer << dynGroupprivateSize << " : " << size_type;
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Parsers for operations including clauses that define entry block arguments.
 //===----------------------------------------------------------------------===//
@@ -1967,6 +2128,12 @@ LogicalResult TargetOp::verify() {
   if (failed(verifyMapClause(*this, getMapVars())))
     return failure();
 
+  // check dyn_groupprivate clause restrictions
+  if (failed(verifyDynGroupprivateClause(*this, getModifierFirstAttr(),
+                                         getModifierSecondAttr(),
+                                         getDynGroupprivateSize())))
+    return failure();
+
   return verifyPrivateVarsMapping(*this);
 }
 
@@ -2374,6 +2541,12 @@ LogicalResult TeamsOp::verify() {
     return emitError(
         "expected equal sizes for allocate and allocator variables");
 
+  // check dyn_groupprivate clause restrictions
+  if (failed(verifyDynGroupprivateClause(op, getModifierFirstAttr(),
+                                         getModifierSecondAttr(),
+                                         getDynGroupprivateSize())))
+    return failure();
+
   return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
                                 getReductionByref());
 }
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 7efc5258f4c23..0d77ddc530cbb 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -1449,6 +1449,26 @@ func.func @omp_teams_num_teams2(%lb : i32, %ub : i16) {
 
 // -----
 
+func.func @test_teams_dyn_groupprivate_errors_1(%dyn_size: i32) {
+  // expected-error @below {{duplicate dyn_groupprivate modifier 'strict'}}
+  omp.teams dyn_groupprivate(strict, strict : %dyn_size : i32) {
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
+func.func @test_teams_dyn_groupprivate_errors_2(%dyn_size: i32) {
+  // expected-error @below {{incompatible dyn_groupprivate modifiers: 'strict' and 'fallback' cannot be used together}}
+  omp.teams dyn_groupprivate(strict, fallback : %dyn_size : i32) {
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
 func.func @omp_sections(%data_var : memref<i32>) -> () {
   // expected-error @below {{expected equal sizes for allocate and allocator variables}}
   "omp.sections" (%data_var) ({
@@ -2441,6 +2461,20 @@ func.func @omp_target_depend(%data_var: memref<i32>) {
 
 // -----
 
+func.func @test_target_dyn_groupprivate_errors(%dyn_size: i32) {
+  // expected-error @below {{duplicate dyn_groupprivate modifier 'strict'}}
+  omp.target dyn_groupprivate(strict, strict : %dyn_size : i32) {
+    omp.terminator
+  }
+  // expected-error @below {{incompatible dyn_groupprivate modifiers: 'strict' and 'fallback' cannot be used together}}
+  omp.target dyn_groupprivate(strict, fallback : %dyn_size : i32) {
+    omp.terminator
+  }
+  return
+}
+
+// -----
+
 func.func @omp_distribute_schedule(%chunk_size : i32, %lb : i32, %ub : i32, %step : i32) -> () {
   // expected-error @below {{op chunk size set without dist_schedule_static being present}}
   "omp.distribute"(%chunk_size) <{operandSegmentSizes = array<i32: 0, 0, 1, 0>}> ({
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 9dbadb219fadb..64be91937ebad 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -1022,7 +1022,7 @@ func.func @parallel_wsloop_reduction(%lb : index, %ub : index, %step : index) {
 
 // CHECK-LABEL: omp_teams
 func.func @omp_teams(%lb : i32, %ub : i32, %if_cond : i1, %num_threads : i32,
-                     %data_var : memref<i32>) -> () {
+                     %dyn_size : i32, %data_var : memref<i32>) -> () {
   // Test nesting inside of omp.target
   omp.target {
     // CHECK: omp.teams
@@ -1092,6 +1092,13 @@ func.func @omp_teams(%lb : i32, %ub : i32, %if_cond : i1, %num_threads : i32,
     // CHECK: omp.terminator
     omp.terminator
   }
+  
+  // Test dyn_groupprivate
+  // CHECK: omp.teams dyn_groupprivate(cgroup, strict : %{{.+}} : i32)
+  omp.teams dyn_groupprivate(cgroup, strict : %dyn_size : i32) {
+    // CHECK: omp.terminator
+    omp.terminator
+  }
 
   return
 }
@@ -2153,6 +2160,28 @@ func.func @omp_target_depend(%arg0: memref<i32>, %arg1: memref<i32>) {
   return
 }
 
+// CHECK-LABEL: @omp_target_dyn_groupprivate
+func.func @omp_target_dyn_groupprivate(%dyn_size: i32, %large_size: i64) {
+  // CHECK: omp.target dyn_groupprivate(strict, cgroup : %{{.*}} : i32)
+  omp.target dyn_groupprivate(strict, cgroup : %dyn_size : i32) {
+    // CHECK: omp.terminator
+    omp.terminator
+  }
+  // CHECK: omp.target dyn_groupprivate(cgroup : %{{.*}} : i64)
+  omp.target dyn_groupprivate(cgroup : %large_size : i64) {
+    omp.terminator
+  }
+  // CHECK: omp.target dyn_groupprivate(fallback, cgroup : %{{.*}} : i32)
+  omp.target dyn_groupprivate(fallback, cgroup : %dyn_size : i32) {
+    omp.terminator
+  }
+  // CHECK: omp.target dyn_groupprivate(%{{.*}} : i64)
+  omp.target dyn_groupprivate(%large_size : i64) {
+    omp.terminator
+  }
+  return
+}
+
 func.func @omp_threadprivate() {
   %0 = arith.constant 1 : i32
   %1 = arith.constant 2 : i32

>From 56a6aa00de8f704b03d7404ed47d49a631cf079d Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Mon, 18 Aug 2025 17:52:07 +0530
Subject: [PATCH 5/5] Fix typo in enum

---
 mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
index 19a7b3dbbc759..9869615f5e885 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td
@@ -304,7 +304,7 @@ def DynGroupprivateFallback : I32EnumAttrCase<"fallback", 2>;
 
 def DynGroupprivateModifier : OpenMP_I32EnumAttr<
     "DynGroupprivateModifier",
-    "reduction modifier", [
+    "dyn_groupprivate modifier", [
       DynGroupprivateCGroup,
       DynGroupprivateStrict,
       DynGroupprivateFallback



More information about the Mlir-commits mailing list