From 719c41abf08c385eb85857e26754ae3ef0c94490 Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Tue, 18 Nov 2025 08:17:03 +0000 Subject: [PATCH 1/2] [mlir][Pass] Fix crash when applying a pass to an optional interface --- mlir/include/mlir/Pass/Pass.h | 8 +++++ mlir/lib/Pass/Pass.cpp | 6 ++-- .../Transform/test-pass-application.mlir | 34 ++++++++++++++++++- mlir/test/Pass/pipeline-invalid.mlir | 2 +- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/mlir/include/mlir/Pass/Pass.h b/mlir/include/mlir/Pass/Pass.h index 16893c6db87b1..448a688243491 100644 --- a/mlir/include/mlir/Pass/Pass.h +++ b/mlir/include/mlir/Pass/Pass.h @@ -193,6 +193,13 @@ class Pass { /// This is useful for generic operation passes to add restrictions on the /// operations they operate on. virtual bool canScheduleOn(RegisteredOperationName opName) const = 0; + virtual bool canScheduleOn(Operation *op) const { + std::optional registeredInfo = + op->getName().getRegisteredInfo(); + if (!registeredInfo) + return false; + return canScheduleOn(*registeredInfo); + } /// Schedule an arbitrary pass pipeline on the provided operation. /// This can be invoke any time in a pass to dynamic schedule more passes. @@ -436,6 +443,7 @@ class InterfacePass : public OperationPass<> { /// Indicate if the current pass can be scheduled on the given operation type. /// For an InterfacePass, this checks if the operation implements the given /// interface. + bool canScheduleOn(Operation *op) const final { return isa(op); } bool canScheduleOn(RegisteredOperationName opName) const final { return opName.hasInterface(); } diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp index 521c7c6be17b6..75f882606e0ab 100644 --- a/mlir/lib/Pass/Pass.cpp +++ b/mlir/lib/Pass/Pass.cpp @@ -559,9 +559,9 @@ LogicalResult OpToOpPassAdaptor::run(Pass *pass, Operation *op, return op->emitOpError() << "trying to schedule a pass on an operation not " "marked as 'IsolatedFromAbove'"; } - if (!pass->canScheduleOn(*op->getName().getRegisteredInfo())) { - return op->emitOpError() - << "trying to schedule a pass on an unsupported operation"; + if (!pass->canScheduleOn(op)) { + return op->emitOpError() << "trying to schedule pass '" << pass->getName() + << "' on an unsupported operation"; } // Initialize the pass state with a callback for the pass to dynamically diff --git a/mlir/test/Dialect/Transform/test-pass-application.mlir b/mlir/test/Dialect/Transform/test-pass-application.mlir index ce8f69c58701d..0d74f5dee73a5 100644 --- a/mlir/test/Dialect/Transform/test-pass-application.mlir +++ b/mlir/test/Dialect/Transform/test-pass-application.mlir @@ -386,7 +386,7 @@ module attributes {transform.with_named_sequence} { // ----- module attributes {transform.with_named_sequence} { - // expected-error @below {{trying to schedule a pass on an unsupported operation}} + // expected-error @below {{trying to schedule pass 'DuplicateFunctionEliminationPass' on an unsupported operation}} // expected-note @below {{target op}} func.func @invalid_target_op_type() { return @@ -475,3 +475,35 @@ module attributes {transform.with_named_sequence} { "transform.yield"() : () -> () }) : () -> () }) {transform.with_named_sequence} : () -> () + +// ----- + +module attributes {transform.with_named_sequence} { + // Unnamed modules do not implement SymbolOpInterface, so test-print-liveness + // cannot be applied. + // expected-error @+2 {{trying to schedule pass '(anonymous namespace)::TestLivenessPass' on an unsupported operation}} + // expected-note @+1 {{target op}} + builtin.module attributes{test.target} {} + + transform.named_sequence @__transform_main(%arg1: !transform.any_op) { + %1 = transform.structured.match ops{["builtin.module"]} attributes {test.target} in %arg1 : (!transform.any_op) -> !transform.any_op + + // expected-error @below {{pass pipeline failed}} + transform.apply_registered_pass "test-print-liveness" to %1 : (!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +module attributes {transform.with_named_sequence} { + // Named modules implement SymbolOpInterface, so test-print-liveness can be + // applied. + builtin.module @named_module attributes{test.target} {} + + transform.named_sequence @__transform_main(%arg1: !transform.any_op) { + %1 = transform.structured.match ops{["builtin.module"]} attributes {test.target} in %arg1 : (!transform.any_op) -> !transform.any_op + transform.apply_registered_pass "test-print-liveness" to %1 : (!transform.any_op) -> !transform.any_op + transform.yield + } +} diff --git a/mlir/test/Pass/pipeline-invalid.mlir b/mlir/test/Pass/pipeline-invalid.mlir index 948a13384bc75..4116e127a24a6 100644 --- a/mlir/test/Pass/pipeline-invalid.mlir +++ b/mlir/test/Pass/pipeline-invalid.mlir @@ -15,5 +15,5 @@ arith.constant 0 // ----- -// expected-error@below {{trying to schedule a pass on an unsupported operation}} +// expected-error@below {{trying to schedule pass '(anonymous namespace)::TestFunctionPass' on an unsupported operation}} module {} From d033d694a03734b009ea91d3f0be1fc7d41efadd Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Thu, 20 Nov 2025 04:08:49 +0000 Subject: [PATCH 2/2] address comments --- .../Transform/test-pass-application.mlir | 32 ------------------- .../Pass/invalid-unsupported-operation.mlir | 10 ++++++ 2 files changed, 10 insertions(+), 32 deletions(-) create mode 100644 mlir/test/Pass/invalid-unsupported-operation.mlir diff --git a/mlir/test/Dialect/Transform/test-pass-application.mlir b/mlir/test/Dialect/Transform/test-pass-application.mlir index 0d74f5dee73a5..4806daf7ce73f 100644 --- a/mlir/test/Dialect/Transform/test-pass-application.mlir +++ b/mlir/test/Dialect/Transform/test-pass-application.mlir @@ -475,35 +475,3 @@ module attributes {transform.with_named_sequence} { "transform.yield"() : () -> () }) : () -> () }) {transform.with_named_sequence} : () -> () - -// ----- - -module attributes {transform.with_named_sequence} { - // Unnamed modules do not implement SymbolOpInterface, so test-print-liveness - // cannot be applied. - // expected-error @+2 {{trying to schedule pass '(anonymous namespace)::TestLivenessPass' on an unsupported operation}} - // expected-note @+1 {{target op}} - builtin.module attributes{test.target} {} - - transform.named_sequence @__transform_main(%arg1: !transform.any_op) { - %1 = transform.structured.match ops{["builtin.module"]} attributes {test.target} in %arg1 : (!transform.any_op) -> !transform.any_op - - // expected-error @below {{pass pipeline failed}} - transform.apply_registered_pass "test-print-liveness" to %1 : (!transform.any_op) -> !transform.any_op - transform.yield - } -} - -// ----- - -module attributes {transform.with_named_sequence} { - // Named modules implement SymbolOpInterface, so test-print-liveness can be - // applied. - builtin.module @named_module attributes{test.target} {} - - transform.named_sequence @__transform_main(%arg1: !transform.any_op) { - %1 = transform.structured.match ops{["builtin.module"]} attributes {test.target} in %arg1 : (!transform.any_op) -> !transform.any_op - transform.apply_registered_pass "test-print-liveness" to %1 : (!transform.any_op) -> !transform.any_op - transform.yield - } -} diff --git a/mlir/test/Pass/invalid-unsupported-operation.mlir b/mlir/test/Pass/invalid-unsupported-operation.mlir new file mode 100644 index 0000000000000..0ff49448c1daf --- /dev/null +++ b/mlir/test/Pass/invalid-unsupported-operation.mlir @@ -0,0 +1,10 @@ +// RUN: mlir-opt %s -test-print-liveness -split-input-file -verify-diagnostics + +// Unnamed modules do not implement SymbolOpInterface. +// expected-error @+1 {{trying to schedule pass '(anonymous namespace)::TestLivenessPass' on an unsupported operation}} +module {} + +// ----- + +// Named modules implement SymbolOpInterface. +module @named_module {}