[mlir][Pass] Fix crash when applying a pass to an optional interface (#168499)
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.
This commit is contained in:
parent
131cf7d5b2
commit
54f69caf1f
@ -193,6 +193,13 @@ protected:
|
||||
/// 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 @@ protected:
|
||||
/// 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>();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
10
mlir/test/Pass/invalid-unsupported-operation.mlir
Normal file
10
mlir/test/Pass/invalid-unsupported-operation.mlir
Normal file
@ -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 {}
|
||||
@ -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 {}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user