Skip to content

Conversation

@matthias-springer
Copy link
Member

Interfaces can be optional: whether an op implements an interface or not can depend on the state of the operation.

  // An optional code block for adding additional "classof" logic. This can
  // be used to better enable "optional" interfaces, where an entity only
  // implements the interface if some dynamic characteristic holds.
  // `$_attr`/`$_op`/`$_type` may be used to refer to an instance of the
  // interface instance being checked.
  code extraClassOf = "";

The current Pass::canScheduleOn(RegisteredOperationName) is insufficient. This commit adds an additional overload to inspect Operation *.

This commit fixes a crash when scheduling an InterfacePass for an optional interface on an operation that does not actually implement the interface.

@llvmbot llvmbot added mlir:core MLIR Core Infrastructure mlir labels Nov 18, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 18, 2025

@llvm/pr-subscribers-mlir-core

@llvm/pr-subscribers-mlir

Author: Matthias Springer (matthias-springer)

Changes

Interfaces can be optional: whether an op implements an interface or not can depend on the state of the operation.

  // An optional code block for adding additional "classof" logic. This can
  // be used to better enable "optional" interfaces, where an entity only
  // implements the interface if some dynamic characteristic holds.
  // `$_attr`/`$_op`/`$_type` may be used to refer to an instance of the
  // interface instance being checked.
  code extraClassOf = "";

The current Pass::canScheduleOn(RegisteredOperationName) is insufficient. This commit adds an additional overload to inspect Operation *.

This commit fixes a crash when scheduling an InterfacePass for an optional interface on an operation that does not actually implement the interface.


Full diff: https://github.com/llvm/llvm-project/pull/168499.diff

3 Files Affected:

  • (modified) mlir/include/mlir/Pass/Pass.h (+8)
  • (modified) mlir/lib/Pass/Pass.cpp (+1-1)
  • (added) mlir/test/Analysis/test-liveness-invalid.mlir (+11)
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<RegisteredOperationName> 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<InterfaceT>(op); }
   bool canScheduleOn(RegisteredOperationName opName) const final {
     return opName.hasInterface<InterfaceT>();
   }
diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp
index 521c7c6be17b6..c904a8d869b6a 100644
--- a/mlir/lib/Pass/Pass.cpp
+++ b/mlir/lib/Pass/Pass.cpp
@@ -559,7 +559,7 @@ 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())) {
+  if (!pass->canScheduleOn(op)) {
     return op->emitOpError()
            << "trying to schedule a pass on an unsupported operation";
   }
diff --git a/mlir/test/Analysis/test-liveness-invalid.mlir b/mlir/test/Analysis/test-liveness-invalid.mlir
new file mode 100644
index 0000000000000..32781e93c7b6e
--- /dev/null
+++ b/mlir/test/Analysis/test-liveness-invalid.mlir
@@ -0,0 +1,11 @@
+
+// RUN: mlir-opt %s -test-print-liveness -split-input-file -verify-diagnostics
+
+// Unnamed modules do not implement SymbolOpInterface.
+// expected-error @+1 {{trying to schedule a pass on an unsupported operation}}
+module {}
+
+// -----
+
+// Named modules implement SymbolOpInterface.
+module @named_module {}

@github-actions
Copy link

github-actions bot commented Nov 18, 2025

🐧 Linux x64 Test Results

  • 7102 tests passed
  • 594 tests skipped

@matthias-springer matthias-springer force-pushed the users/matthias-springer/fix_crash_passm branch from 25a8fb6 to 719c41a Compare November 19, 2025 01:55
@matthias-springer matthias-springer merged commit 54f69ca into main Nov 20, 2025
10 checks passed
@matthias-springer matthias-springer deleted the users/matthias-springer/fix_crash_passm branch November 20, 2025 09:51
@llvm-ci
Copy link
Collaborator

llvm-ci commented Nov 20, 2025

LLVM Buildbot has detected a new failure on builder mlir-nvidia-gcc7 running on mlir-nvidia while building mlir at step 7 "test-build-check-mlir-build-only-check-mlir".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/116/builds/21238

Here is the relevant piece of the build log for the reference
Step 7 (test-build-check-mlir-build-only-check-mlir) failure: test (failure)
******************** TEST 'MLIR :: Pass/invalid-unsupported-operation.mlir' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
/vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.obj/bin/mlir-opt /vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.src/mlir/test/Pass/invalid-unsupported-operation.mlir -test-print-liveness -split-input-file -verify-diagnostics
# executed command: /vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.obj/bin/mlir-opt /vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.src/mlir/test/Pass/invalid-unsupported-operation.mlir -test-print-liveness -split-input-file -verify-diagnostics
# .---command stdout------------
# | // -----
# | module @named_module {
# | }
# | 
# `-----------------------------
# .---command stderr------------
# | /vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.src/mlir/test/Pass/invalid-unsupported-operation.mlir:5:1: error: unexpected error: 'builtin.module' op trying to schedule pass '{anonymous}::TestLivenessPass' on an unsupported operation
# | module {}
# | ^
# | Testing : named_module
# | // ---- Liveness -----
# | // - Block: 0
# | // --- LiveIn: 
# | // --- LiveOut: 
# | // --- BeginLivenessIntervals
# | // --- EndLivenessIntervals
# | // --- BeginCurrentlyLive
# | // --- EndCurrentlyLive
# | // -------------------
# | /vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.src/mlir/test/Pass/invalid-unsupported-operation.mlir:4:4: error: expected error "trying to schedule pass '(anonymous namespace)::TestLivenessPass' on an unsupported operation" was not produced
# | // expected-error @+1 {{trying to schedule pass '(anonymous namespace)::TestLivenessPass' on an unsupported operation}}
# |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# `-----------------------------
# error: command failed with exit status: 1

--

********************


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mlir:core MLIR Core Infrastructure mlir

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants