[Mlir-commits] [mlir] [MLIR][Interfaces] Make `getMutableSuccessorOperands` overridable on `ReturnLike` ops (PR #186832)

Robert Konicar llvmlistbot at llvm.org
Tue Mar 17 05:27:50 PDT 2026


https://github.com/Jezurko updated https://github.com/llvm/llvm-project/pull/186832

>From fc04f20d0adbd8147ec9704d7002e835780920de Mon Sep 17 00:00:00 2001
From: Robert Konicar <robert.konicar at nextsilicon.com>
Date: Mon, 16 Mar 2026 16:57:29 +0100
Subject: [PATCH 1/2] [MLIR][Interfaces] Make `getMutableSuccessorOperands`
 overridable on `ReturnLike` ops

Move the `getMutableSuccessorOperands` implementation from `ReturnLike` trait to the
`RegionBranchTerminatorOpInterface` to allow overriding of the implementation.
This allows to have the trait on operations that are not a return of all of their
operands.
---
 .../mlir/Dialect/OpenACC/OpenACCOps.td        |  3 +-
 mlir/include/mlir/Dialect/SCF/IR/SCFOps.td    | 21 ++++-----
 .../mlir/Interfaces/ControlFlowInterfaces.td  | 45 ++++++++-----------
 mlir/test/lib/Dialect/Test/TestOpDefs.cpp     |  9 ++++
 mlir/test/lib/Dialect/Test/TestOps.td         | 26 ++++++++---
 5 files changed, 61 insertions(+), 43 deletions(-)

diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 25e3dbd29043d..c8030b14e96c1 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -2354,7 +2354,8 @@ def OpenACC_DataOp
 def OpenACC_TerminatorOp
     : OpenACC_Op<"terminator", [Pure, Terminator,
                                 DeclareOpInterfaceMethods<
-                                    RegionBranchTerminatorOpInterface>]> {
+                                    RegionBranchTerminatorOpInterface,
+                                    ["getMutableSuccessorOperands"]>]> {
   let summary = "Generic terminator for OpenACC regions";
 
   let description = [{
diff --git a/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td b/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td
index a08cf3c95e6ce..54e40f9e99d73 100644
--- a/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td
+++ b/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td
@@ -51,13 +51,12 @@ class SCF_Op<string mnemonic, list<Trait> traits = []> :
 // ConditionOp
 //===----------------------------------------------------------------------===//
 
-def ConditionOp : SCF_Op<"condition", [
-  HasParent<"WhileOp">,
-  DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
-    ["getSuccessorRegions"]>,
-  Pure,
-  Terminator
-]> {
+def ConditionOp : SCF_Op<"condition", [HasParent<"WhileOp">,
+                                       DeclareOpInterfaceMethods<
+                                           RegionBranchTerminatorOpInterface,
+                                           ["getSuccessorRegions",
+                                            "getMutableSuccessorOperands"]>,
+                                       Pure, Terminator]> {
   let summary = "loop continuation condition";
   let description = [{
     This operation accepts the continuation (i.e., inverse of exit) condition
@@ -902,9 +901,11 @@ def ParallelOp : SCF_Op<"parallel",
 // ReduceOp
 //===----------------------------------------------------------------------===//
 
-def ReduceOp : SCF_Op<"reduce", [
-    Terminator, HasParent<"ParallelOp">, RecursiveMemoryEffects,
-    DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>]> {
+def ReduceOp
+    : SCF_Op<"reduce",
+             [Terminator, HasParent<"ParallelOp">, RecursiveMemoryEffects,
+              DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
+                                        ["getMutableSuccessorOperands"]>]> {
   let summary = "reduce operation for scf.parallel";
   let description = [{
     The `scf.reduce` operation is the terminator for `scf.parallel` operations. It can model
diff --git a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
index 8975b1235a7e3..1f2db92bd7691 100644
--- a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
+++ b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
@@ -426,15 +426,19 @@ def RegionBranchTerminatorOpInterface :
   }];
   let cppNamespace = "::mlir";
 
-  let methods = [
-    InterfaceMethod<[{
+  let methods =
+      [InterfaceMethod<[{
         Returns a mutable range of operands that are semantically "returned" by
         passing them to the region successor indicated by `point`.
       }],
-      "::mlir::MutableOperandRange", "getMutableSuccessorOperands",
-      (ins "::mlir::RegionSuccessor":$point)
-    >,
-    InterfaceMethod<[{
+                       "::mlir::MutableOperandRange",
+                       "getMutableSuccessorOperands",
+                       (ins "::mlir::RegionSuccessor":$point), [{}],
+                       /*defaultImplementation=*/[{
+        return ::mlir::MutableOperandRange($_op);
+      }]>,
+       InterfaceMethod<
+           [{
         Returns the potential region successors that are branched to after this
         terminator based on the given constant operands.
 
@@ -445,15 +449,15 @@ def RegionBranchTerminatorOpInterface :
         The default implementation simply dispatches to the parent
         `RegionBranchOpInterface`'s `getSuccessorRegions` implementation.
       }],
-      "void", "getSuccessorRegions",
-      (ins "::llvm::ArrayRef<::mlir::Attribute>":$operands,
-           "::llvm::SmallVectorImpl<::mlir::RegionSuccessor> &":$regions), [{}],
-      /*defaultImplementation=*/[{
+           "void", "getSuccessorRegions",
+           (ins "::llvm::ArrayRef<::mlir::Attribute>":$operands,
+               "::llvm::SmallVectorImpl<::mlir::RegionSuccessor> &":$regions),
+           [{}],
+           /*defaultImplementation=*/[{
         ::mlir::Operation *op = $_op;
         ::llvm::cast<::mlir::RegionBranchOpInterface>(op->getParentOp())
           .getSuccessorRegions(::llvm::cast<::mlir::RegionBranchTerminatorOpInterface>(op), regions);
-      }]
-    >,
+      }]>,
   ];
 
   let verify = [{
@@ -630,19 +634,8 @@ def WeightedRegionBranchOpInterface
 //===----------------------------------------------------------------------===//
 
 // Op is "return-like".
-def ReturnLike : TraitList<[
-    DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>,
-    NativeOpTrait<
-        /*name=*/"ReturnLike",
-        /*traits=*/[],
-        /*extraOpDeclaration=*/"",
-        /*extraOpDefinition=*/[{
-          ::mlir::MutableOperandRange $cppClass::getMutableSuccessorOperands(
-            ::mlir::RegionSuccessor successor) {
-            return ::mlir::MutableOperandRange(*this);
-          }
-        }]
-    >
-]>;
+def ReturnLike
+    : TraitList<[DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>,
+                 NativeOpTrait</*name=*/"ReturnLike">]>;
 
 #endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES
diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
index bd825c858a615..ed5dc5bead78a 100644
--- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
@@ -1331,6 +1331,15 @@ TestCrashingReturnOp::getMutableSuccessorOperands(RegionSuccessor successor) {
   return getArgsMutable();
 }
 
+//===----------------------------------------------------------------------===//
+// TestReturnWithIgnoredValueOp
+//===----------------------------------------------------------------------===//
+
+MutableOperandRange TestReturnWithIgnoredValueOp::getMutableSuccessorOperands(
+    RegionSuccessor /*successor*/) {
+  return getValuesMutable();
+}
+
 //===----------------------------------------------------------------------===//
 // SwitchWithNoBreakOp
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 02bac016eeed1..3f935ae550203 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -2243,9 +2243,11 @@ def TestReturnOp : TEST_Op<"return", [Pure, ReturnLike, Terminator]> {
 // When 'valid' unit-attr is absent the op is malformed; its verifier
 // emits an error, but getMutableSuccessorOperands() calls report_fatal_error
 // to expose the fact that FuncOp::verify() runs before the region is checked.
-def TestCrashingReturnOp : TEST_Op<"crashing_return", [
-    DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>,
-    Terminator]> {
+def TestCrashingReturnOp
+    : TEST_Op<"crashing_return", [DeclareOpInterfaceMethods<
+                                      RegionBranchTerminatorOpInterface,
+                                      ["getMutableSuccessorOperands"]>,
+                                  Terminator]> {
   let arguments = (ins Variadic<AnyType>:$args, UnitAttr:$valid);
   let assemblyFormat = "($args^ `:` type($args))? attr-dict";
   let hasVerifier = 1;
@@ -2300,6 +2302,16 @@ def TestSignatureConversionNoConverterOp
   let regions = (region AnyRegion);
 }
 
+// A return-like operation with override on the successor operand getter
+// interface method.
+def TestReturnWithIgnoredValueOp
+    : TEST_Op<"return_with_ignored_value",
+              [Pure, ReturnLike, Terminator,
+               DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
+                                         ["getMutableSuccessorOperands"]>]> {
+  let arguments = (ins Variadic<AnyType>:$values, AnyType:$unwanted_value);
+}
+
 //===----------------------------------------------------------------------===//
 // Test parser.
 //===----------------------------------------------------------------------===//
@@ -2706,9 +2718,11 @@ def LoopBlockOp : TEST_Op<"loop_block",
   }];
 }
 
-def LoopBlockTerminatorOp : TEST_Op<"loop_block_term",
-    [DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>, Pure,
-     Terminator]> {
+def LoopBlockTerminatorOp
+    : TEST_Op<"loop_block_term", [DeclareOpInterfaceMethods<
+                                      RegionBranchTerminatorOpInterface,
+                                      ["getMutableSuccessorOperands"]>,
+                                  Pure, Terminator]> {
   let arguments = (ins I32:$nextIterArg, F32:$exitArg);
 
   let assemblyFormat = [{

>From 03b9223ae3ab075d6d3dbea918181539ad99f644 Mon Sep 17 00:00:00 2001
From: Robert Konicar <robert.konicar at nextsilicon.com>
Date: Tue, 17 Mar 2026 13:08:53 +0100
Subject: [PATCH 2/2] fixup! [MLIR][Interfaces] Make
 `getMutableSuccessorOperands` overridable on `ReturnLike` ops

---
 mlir/include/mlir/Dialect/SCF/IR/SCFOps.td    | 22 ++++++------
 .../mlir/Interfaces/ControlFlowInterfaces.td  | 36 +++++++++----------
 mlir/test/lib/Dialect/Test/TestOps.td         | 31 ++++++++--------
 3 files changed, 45 insertions(+), 44 deletions(-)

diff --git a/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td b/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td
index 54e40f9e99d73..6ed85c611983a 100644
--- a/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td
+++ b/mlir/include/mlir/Dialect/SCF/IR/SCFOps.td
@@ -51,12 +51,13 @@ class SCF_Op<string mnemonic, list<Trait> traits = []> :
 // ConditionOp
 //===----------------------------------------------------------------------===//
 
-def ConditionOp : SCF_Op<"condition", [HasParent<"WhileOp">,
-                                       DeclareOpInterfaceMethods<
-                                           RegionBranchTerminatorOpInterface,
-                                           ["getSuccessorRegions",
-                                            "getMutableSuccessorOperands"]>,
-                                       Pure, Terminator]> {
+def ConditionOp : SCF_Op<"condition", [
+  HasParent<"WhileOp">,
+  DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
+    ["getSuccessorRegions", "getMutableSuccessorOperands"]>,
+  Pure,
+  Terminator
+]> {
   let summary = "loop continuation condition";
   let description = [{
     This operation accepts the continuation (i.e., inverse of exit) condition
@@ -901,11 +902,10 @@ def ParallelOp : SCF_Op<"parallel",
 // ReduceOp
 //===----------------------------------------------------------------------===//
 
-def ReduceOp
-    : SCF_Op<"reduce",
-             [Terminator, HasParent<"ParallelOp">, RecursiveMemoryEffects,
-              DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
-                                        ["getMutableSuccessorOperands"]>]> {
+def ReduceOp : SCF_Op<"reduce", [
+    Terminator, HasParent<"ParallelOp">, RecursiveMemoryEffects,
+    DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
+                              ["getMutableSuccessorOperands"]>]> {
   let summary = "reduce operation for scf.parallel";
   let description = [{
     The `scf.reduce` operation is the terminator for `scf.parallel` operations. It can model
diff --git a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
index 1f2db92bd7691..06fa724e05fab 100644
--- a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
+++ b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
@@ -426,19 +426,19 @@ def RegionBranchTerminatorOpInterface :
   }];
   let cppNamespace = "::mlir";
 
-  let methods =
-      [InterfaceMethod<[{
+  let methods = [
+    InterfaceMethod<[{
         Returns a mutable range of operands that are semantically "returned" by
         passing them to the region successor indicated by `point`.
       }],
-                       "::mlir::MutableOperandRange",
-                       "getMutableSuccessorOperands",
-                       (ins "::mlir::RegionSuccessor":$point), [{}],
-                       /*defaultImplementation=*/[{
+      "::mlir::MutableOperandRange", "getMutableSuccessorOperands",
+      (ins "::mlir::RegionSuccessor":$point),
+      [{}],
+      /*defaultImplementation=*/[{
         return ::mlir::MutableOperandRange($_op);
-      }]>,
-       InterfaceMethod<
-           [{
+      }]
+    >,
+    InterfaceMethod<[{
         Returns the potential region successors that are branched to after this
         terminator based on the given constant operands.
 
@@ -449,15 +449,15 @@ def RegionBranchTerminatorOpInterface :
         The default implementation simply dispatches to the parent
         `RegionBranchOpInterface`'s `getSuccessorRegions` implementation.
       }],
-           "void", "getSuccessorRegions",
-           (ins "::llvm::ArrayRef<::mlir::Attribute>":$operands,
-               "::llvm::SmallVectorImpl<::mlir::RegionSuccessor> &":$regions),
-           [{}],
-           /*defaultImplementation=*/[{
+      "void", "getSuccessorRegions",
+      (ins "::llvm::ArrayRef<::mlir::Attribute>":$operands,
+           "::llvm::SmallVectorImpl<::mlir::RegionSuccessor> &":$regions), [{}],
+      /*defaultImplementation=*/[{
         ::mlir::Operation *op = $_op;
         ::llvm::cast<::mlir::RegionBranchOpInterface>(op->getParentOp())
           .getSuccessorRegions(::llvm::cast<::mlir::RegionBranchTerminatorOpInterface>(op), regions);
-      }]>,
+      }]
+    >,
   ];
 
   let verify = [{
@@ -634,8 +634,8 @@ def WeightedRegionBranchOpInterface
 //===----------------------------------------------------------------------===//
 
 // Op is "return-like".
-def ReturnLike
-    : TraitList<[DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>,
-                 NativeOpTrait</*name=*/"ReturnLike">]>;
+def ReturnLike : TraitList<[
+    DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface>,
+    NativeOpTrait</*name=*/"ReturnLike">]>;
 
 #endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES
diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 3f935ae550203..4c9e6b3fe9e45 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -2243,11 +2243,10 @@ def TestReturnOp : TEST_Op<"return", [Pure, ReturnLike, Terminator]> {
 // When 'valid' unit-attr is absent the op is malformed; its verifier
 // emits an error, but getMutableSuccessorOperands() calls report_fatal_error
 // to expose the fact that FuncOp::verify() runs before the region is checked.
-def TestCrashingReturnOp
-    : TEST_Op<"crashing_return", [DeclareOpInterfaceMethods<
-                                      RegionBranchTerminatorOpInterface,
-                                      ["getMutableSuccessorOperands"]>,
-                                  Terminator]> {
+def TestCrashingReturnOp : TEST_Op<"crashing_return", [
+    DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
+       ["getMutableSuccessorOperands"]>,
+    Terminator]> {
   let arguments = (ins Variadic<AnyType>:$args, UnitAttr:$valid);
   let assemblyFormat = "($args^ `:` type($args))? attr-dict";
   let hasVerifier = 1;
@@ -2304,11 +2303,14 @@ def TestSignatureConversionNoConverterOp
 
 // A return-like operation with override on the successor operand getter
 // interface method.
-def TestReturnWithIgnoredValueOp
-    : TEST_Op<"return_with_ignored_value",
-              [Pure, ReturnLike, Terminator,
-               DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
-                                         ["getMutableSuccessorOperands"]>]> {
+def TestReturnWithIgnoredValueOp : TEST_Op<"return_with_ignored_value", [
+    Pure,
+    ReturnLike,
+    DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface, [
+      "getMutableSuccessorOperands"
+    ]>,
+    Terminator
+]> {
   let arguments = (ins Variadic<AnyType>:$values, AnyType:$unwanted_value);
 }
 
@@ -2718,11 +2720,10 @@ def LoopBlockOp : TEST_Op<"loop_block",
   }];
 }
 
-def LoopBlockTerminatorOp
-    : TEST_Op<"loop_block_term", [DeclareOpInterfaceMethods<
-                                      RegionBranchTerminatorOpInterface,
-                                      ["getMutableSuccessorOperands"]>,
-                                  Pure, Terminator]> {
+def LoopBlockTerminatorOp : TEST_Op<"loop_block_term",
+    [DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
+        ["getMutableSuccessorOperands"]>,
+     Pure, Terminator]> {
   let arguments = (ins I32:$nextIterArg, F32:$exitArg);
 
   let assemblyFormat = [{



More information about the Mlir-commits mailing list