[Mlir-commits] [mlir] [MLIR] Configure CompositeFixedPointPass's convergence-failure behavior (PR #218394)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Aug 24 05:49:39 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Vadim Curcă (VadimCurca)
<details>
<summary>Changes</summary>
Add an option to `CompositeFixedPointPass` controlling what happens if the pass fails to converge within max-iterations: emit a warning (default), emit an error and fail the pass, or do nothing.
---
Full diff: https://github.com/llvm/llvm-project/pull/218394.diff
6 Files Affected:
- (added) mlir/include/mlir/Transforms/CompositePass.h (+27)
- (modified) mlir/include/mlir/Transforms/Passes.h (+4-1)
- (modified) mlir/include/mlir/Transforms/Passes.td (+12)
- (modified) mlir/lib/Transforms/CompositePass.cpp (+19-7)
- (added) mlir/test/Transforms/composite-pass-convergence-failure.mlir (+18)
- (modified) mlir/test/lib/Transforms/TestCompositePass.cpp (+30)
``````````diff
diff --git a/mlir/include/mlir/Transforms/CompositePass.h b/mlir/include/mlir/Transforms/CompositePass.h
new file mode 100644
index 0000000000000..8fe117c3c41a0
--- /dev/null
+++ b/mlir/include/mlir/Transforms/CompositePass.h
@@ -0,0 +1,27 @@
+//===- CompositePass.h - Composite pass utilities ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TRANSFORMS_COMPOSITEPASS_H
+#define MLIR_TRANSFORMS_COMPOSITEPASS_H
+
+namespace mlir {
+
+/// Action to take when `CompositeFixedPointPass` fails to converge within
+/// its configured maximum number of iterations.
+enum class ConvergenceFailureAction {
+ /// Emit a warning.
+ Warn,
+ /// Emit an error and fail the pass.
+ Error,
+ /// Do nothing.
+ Silent,
+};
+
+} // namespace mlir
+
+#endif // MLIR_TRANSFORMS_COMPOSITEPASS_H
diff --git a/mlir/include/mlir/Transforms/Passes.h b/mlir/include/mlir/Transforms/Passes.h
index 313755fde3479..51c8934f9df86 100644
--- a/mlir/include/mlir/Transforms/Passes.h
+++ b/mlir/include/mlir/Transforms/Passes.h
@@ -16,6 +16,7 @@
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
+#include "mlir/Transforms/CompositePass.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Transforms/LocationSnapshot.h"
#include "mlir/Transforms/ViewOpGraph.h"
@@ -92,7 +93,9 @@ std::unique_ptr<Pass> createPrintOpStatsPass(raw_ostream &os, bool printAsJSON);
/// or maximum number of iterations reached.
std::unique_ptr<Pass> createCompositeFixedPointPass(
std::string name, llvm::function_ref<void(OpPassManager &)> populateFunc,
- int maxIterations = 10);
+ int maxIterations = 10,
+ ConvergenceFailureAction convergenceFailureAction =
+ ConvergenceFailureAction::Warn);
//===----------------------------------------------------------------------===//
// Registration
diff --git a/mlir/include/mlir/Transforms/Passes.td b/mlir/include/mlir/Transforms/Passes.td
index 74ac370ea950b..0af26837fb5e9 100644
--- a/mlir/include/mlir/Transforms/Passes.td
+++ b/mlir/include/mlir/Transforms/Passes.td
@@ -609,6 +609,18 @@ def CompositeFixedPointPass : Pass<"composite-fixed-point-pass"> {
"Composite pass inner pipeline">,
Option<"maxIter", "max-iterations", "int", /*default=*/"10",
"Maximum number of iterations if inner pipeline">,
+ Option<"convergenceFailureAction", "on-convergence-failure",
+ "mlir::ConvergenceFailureAction",
+ /*default=*/"mlir::ConvergenceFailureAction::Warn",
+ "Action to take if the pass fails to converge within max-iterations",
+ [{::llvm::cl::values(
+ clEnumValN(mlir::ConvergenceFailureAction::Warn, "warn",
+ "Emit a warning (default)"),
+ clEnumValN(mlir::ConvergenceFailureAction::Error, "error",
+ "Emit an error and fail the pass"),
+ clEnumValN(mlir::ConvergenceFailureAction::Silent, "silent",
+ "Do nothing")
+ )}]>,
];
}
diff --git a/mlir/lib/Transforms/CompositePass.cpp b/mlir/lib/Transforms/CompositePass.cpp
index cb806c65972a8..d5d2e1fcefae5 100644
--- a/mlir/lib/Transforms/CompositePass.cpp
+++ b/mlir/lib/Transforms/CompositePass.cpp
@@ -29,9 +29,10 @@ struct CompositeFixedPointPass final
CompositeFixedPointPass(
std::string name_, llvm::function_ref<void(OpPassManager &)> populateFunc,
- int maxIterations) {
+ int maxIterations, ConvergenceFailureAction convergenceFailureActionArg) {
name = std::move(name_);
maxIter = maxIterations;
+ convergenceFailureAction = convergenceFailureActionArg;
populateFunc(dynamicPM);
llvm::raw_string_ostream os(pipelineStr);
@@ -76,9 +77,20 @@ struct CompositeFixedPointPass final
return signalPassFailure();
if (currentIter++ >= maxIterVal) {
- op->emitWarning("Composite pass \"" + llvm::Twine(name) +
- "\"+ didn't converge in " + llvm::Twine(maxIterVal) +
- " iterations");
+ std::string message = ("Composite pass \"" + llvm::Twine(name) +
+ "\"+ didn't converge in " +
+ llvm::Twine(maxIterVal) + " iterations")
+ .str();
+ switch (convergenceFailureAction) {
+ case ConvergenceFailureAction::Warn:
+ op->emitWarning(message);
+ break;
+ case ConvergenceFailureAction::Error:
+ op->emitError(message);
+ return signalPassFailure();
+ case ConvergenceFailureAction::Silent:
+ break;
+ }
break;
}
@@ -100,8 +112,8 @@ struct CompositeFixedPointPass final
std::unique_ptr<Pass> mlir::createCompositeFixedPointPass(
std::string name, llvm::function_ref<void(OpPassManager &)> populateFunc,
- int maxIterations) {
+ int maxIterations, ConvergenceFailureAction convergenceFailureAction) {
- return std::make_unique<CompositeFixedPointPass>(std::move(name),
- populateFunc, maxIterations);
+ return std::make_unique<CompositeFixedPointPass>(
+ std::move(name), populateFunc, maxIterations, convergenceFailureAction);
}
diff --git a/mlir/test/Transforms/composite-pass-convergence-failure.mlir b/mlir/test/Transforms/composite-pass-convergence-failure.mlir
new file mode 100644
index 0000000000000..48019dc949f26
--- /dev/null
+++ b/mlir/test/Transforms/composite-pass-convergence-failure.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-opt %s --composite-fixed-point-pass="name=Test pipeline='any(test-increment-attr)' max-iterations=3 on-convergence-failure=warn" 2>&1 | FileCheck %s --check-prefix=CHECK-WARN
+// RUN: not mlir-opt %s --composite-fixed-point-pass="name=Test pipeline='any(test-increment-attr)' max-iterations=3 on-convergence-failure=error" 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: mlir-opt %s --composite-fixed-point-pass="name=Test pipeline='any(test-increment-attr)' max-iterations=3 on-convergence-failure=silent" 2>&1 | FileCheck %s --check-prefix=CHECK-SILENT
+
+// The "test-increment-attr" pass mutates the op on every run, so the composite
+// pass never reaches a fixed point and always exhausts max-iterations,
+// regardless of the input IR.
+
+// CHECK-WARN: warning: Composite pass "Test"+ didn't converge in 3 iterations
+// CHECK-WARN: test.counter = 4
+
+// CHECK-ERROR: error: Composite pass "Test"+ didn't converge in 3 iterations
+
+// CHECK-SILENT-NOT: didn't converge
+// CHECK-SILENT: test.counter = 4
+func.func @test() {
+ return
+}
diff --git a/mlir/test/lib/Transforms/TestCompositePass.cpp b/mlir/test/lib/Transforms/TestCompositePass.cpp
index 5c0d93cc0d64e..9db2281162ce9 100644
--- a/mlir/test/lib/Transforms/TestCompositePass.cpp
+++ b/mlir/test/lib/Transforms/TestCompositePass.cpp
@@ -10,11 +10,39 @@
//
//===----------------------------------------------------------------------===//
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Transforms/Passes.h"
+using namespace mlir;
+
+namespace {
+/// A pass that increments an attribute on the operation on every run,
+/// guaranteeing that it never reaches a fixed point. Used to test
+/// `CompositeFixedPointPass`'s convergence-failure handling.
+struct TestIncrementAttrPass
+ : public PassWrapper<TestIncrementAttrPass, OperationPass<>> {
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestIncrementAttrPass)
+
+ StringRef getArgument() const final { return "test-increment-attr"; }
+ StringRef getDescription() const final {
+ return "Test pass that increments an attribute on the operation on "
+ "every run, so it never reaches a fixed point";
+ }
+
+ void runOnOperation() override {
+ Operation *op = getOperation();
+ int64_t counter = 0;
+ if (auto attr = op->getAttrOfType<IntegerAttr>("test.counter"))
+ counter = attr.getInt();
+ op->setAttr("test.counter", Builder(op).getI64IntegerAttr(counter + 1));
+ }
+};
+} // namespace
+
namespace mlir {
namespace test {
void registerTestCompositePass() {
@@ -33,6 +61,8 @@ void registerTestCompositePass() {
return success();
},
[](function_ref<void(const detail::PassOptions &)>) {});
+
+ PassRegistration<TestIncrementAttrPass>();
}
} // namespace test
} // namespace mlir
``````````
</details>
https://github.com/llvm/llvm-project/pull/218394
More information about the Mlir-commits
mailing list