[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