Skip to content

Commit 0ea3cc1

Browse files
committed
[MLIR][diag] Add PassManager option to emit failed pass name
1 parent 4b84223 commit 0ea3cc1

File tree

6 files changed

+74
-22
lines changed

6 files changed

+74
-22
lines changed

mlir/include/mlir/Pass/PassManager.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ class PassManager : public OpPassManager {
275275
/// Runs the verifier after each individual pass.
276276
void enableVerifier(bool enabled = true);
277277

278+
/// Sets whether an error containing the failing pass name should be emitted
279+
/// upon failure.
280+
void enableErrorOnFailure(bool enabled = true);
281+
278282
//===--------------------------------------------------------------------===//
279283
// Instrumentations
280284
//===--------------------------------------------------------------------===//
@@ -497,6 +501,10 @@ class PassManager : public OpPassManager {
497501

498502
/// A flag that indicates if the IR should be verified in between passes.
499503
bool verifyPasses : 1;
504+
505+
/// A flag that indicates if an error containing the pass name should be
506+
/// emitted upon failure.
507+
bool emitErrorOnFailure : 1;
500508
};
501509

502510
/// Register a set of useful command-line options that can be used to configure

mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,15 @@ class MlirOptMainConfig {
207207
}
208208
bool shouldVerifyPasses() const { return verifyPassesFlag; }
209209

210+
/// Set whether to emit and error upon pass failure.
211+
MlirOptMainConfig &emitErrorOnPassFailure(bool emit) {
212+
emitErrorOnPassFailureFlag = emit;
213+
return *this;
214+
}
215+
bool shouldEmitErrorOnPassFailure() const {
216+
return emitErrorOnPassFailureFlag;
217+
}
218+
210219
/// Set whether to run the verifier on parsing.
211220
MlirOptMainConfig &verifyOnParsing(bool verify) {
212221
disableVerifierOnParsingFlag = !verify;
@@ -291,6 +300,9 @@ class MlirOptMainConfig {
291300
/// Run the verifier after each transformation pass.
292301
bool verifyPassesFlag = true;
293302

303+
/// Emit an error upon a pass failure.
304+
bool emitErrorOnPassFailureFlag = false;
305+
294306
/// Disable the verifier on parsing.
295307
bool disableVerifierOnParsingFlag = false;
296308

mlir/lib/Pass/Pass.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ llvm::hash_code OpPassManager::hash() {
498498

499499
LogicalResult OpToOpPassAdaptor::run(Pass *pass, Operation *op,
500500
AnalysisManager am, bool verifyPasses,
501+
bool emitErrorOnFailure,
501502
unsigned parentInitGeneration) {
502503
std::optional<RegisteredOperationName> opInfo = op->getRegisteredInfo();
503504
if (!opInfo)
@@ -533,9 +534,9 @@ LogicalResult OpToOpPassAdaptor::run(Pass *pass, Operation *op,
533534
if (failed(pipeline.initialize(root->getContext(), parentInitGeneration)))
534535
return failure();
535536
AnalysisManager nestedAm = root == op ? am : am.nest(root);
536-
return OpToOpPassAdaptor::runPipeline(pipeline, root, nestedAm,
537-
verifyPasses, parentInitGeneration,
538-
pi, &parentInfo);
537+
return OpToOpPassAdaptor::runPipeline(
538+
pipeline, root, nestedAm, verifyPasses, emitErrorOnFailure,
539+
parentInitGeneration, pi, &parentInfo);
539540
};
540541
pass->passState.emplace(op, am, dynamicPipelineCallback);
541542

@@ -548,7 +549,7 @@ LogicalResult OpToOpPassAdaptor::run(Pass *pass, Operation *op,
548549
[&]() {
549550
// Invoke the virtual runOnOperation method.
550551
if (auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass))
551-
adaptor->runOnOperation(verifyPasses);
552+
adaptor->runOnOperation(verifyPasses, emitErrorOnFailure);
552553
else
553554
pass->runOnOperation();
554555
passFailed = pass->passState->irAndPassFailed.getInt();
@@ -597,7 +598,8 @@ LogicalResult OpToOpPassAdaptor::run(Pass *pass, Operation *op,
597598
/// Run the given operation and analysis manager on a provided op pass manager.
598599
LogicalResult OpToOpPassAdaptor::runPipeline(
599600
OpPassManager &pm, Operation *op, AnalysisManager am, bool verifyPasses,
600-
unsigned parentInitGeneration, PassInstrumentor *instrumentor,
601+
bool emitErrorOnFailure, unsigned parentInitGeneration,
602+
PassInstrumentor *instrumentor,
601603
const PassInstrumentation::PipelineParentInfo *parentInfo) {
602604
assert((!instrumentor || parentInfo) &&
603605
"expected parent info if instrumentor is provided");
@@ -616,8 +618,12 @@ LogicalResult OpToOpPassAdaptor::runPipeline(
616618
}
617619

618620
for (Pass &pass : pm.getPasses())
619-
if (failed(run(&pass, op, am, verifyPasses, parentInitGeneration)))
621+
if (failed(run(&pass, op, am, verifyPasses, emitErrorOnFailure,
622+
parentInitGeneration))) {
623+
if (emitErrorOnFailure)
624+
return op->emitError("failed to run pass: ") << pass.getName();
620625
return failure();
626+
}
621627

622628
if (instrumentor) {
623629
instrumentor->runAfterPipeline(pm.getOpName(*op->getContext()),
@@ -735,15 +741,17 @@ void OpToOpPassAdaptor::runOnOperation() {
735741
}
736742

737743
/// Run the held pipeline over all nested operations.
738-
void OpToOpPassAdaptor::runOnOperation(bool verifyPasses) {
744+
void OpToOpPassAdaptor::runOnOperation(bool verifyPasses,
745+
bool emitErrorOnFailure) {
739746
if (getContext().isMultithreadingEnabled())
740-
runOnOperationAsyncImpl(verifyPasses);
747+
runOnOperationAsyncImpl(verifyPasses, emitErrorOnFailure);
741748
else
742-
runOnOperationImpl(verifyPasses);
749+
runOnOperationImpl(verifyPasses, emitErrorOnFailure);
743750
}
744751

745752
/// Run this pass adaptor synchronously.
746-
void OpToOpPassAdaptor::runOnOperationImpl(bool verifyPasses) {
753+
void OpToOpPassAdaptor::runOnOperationImpl(bool verifyPasses,
754+
bool emitErrorOnFailure) {
747755
auto am = getAnalysisManager();
748756
PassInstrumentation::PipelineParentInfo parentInfo = {llvm::get_threadid(),
749757
this};
@@ -758,7 +766,8 @@ void OpToOpPassAdaptor::runOnOperationImpl(bool verifyPasses) {
758766
// Run the held pipeline over the current operation.
759767
unsigned initGeneration = mgr->impl->initializationGeneration;
760768
if (failed(runPipeline(*mgr, &op, am.nest(&op), verifyPasses,
761-
initGeneration, instrumentor, &parentInfo)))
769+
emitErrorOnFailure, initGeneration, instrumentor,
770+
&parentInfo)))
762771
signalPassFailure();
763772
}
764773
}
@@ -775,7 +784,8 @@ static bool hasSizeMismatch(ArrayRef<OpPassManager> lhs,
775784
}
776785

777786
/// Run this pass adaptor synchronously.
778-
void OpToOpPassAdaptor::runOnOperationAsyncImpl(bool verifyPasses) {
787+
void OpToOpPassAdaptor::runOnOperationAsyncImpl(bool verifyPasses,
788+
bool emitErrorOnFailure) {
779789
AnalysisManager am = getAnalysisManager();
780790
MLIRContext *context = &getContext();
781791

@@ -838,7 +848,7 @@ void OpToOpPassAdaptor::runOnOperationAsyncImpl(bool verifyPasses) {
838848
// Get the pass manager for this operation and execute it.
839849
OpPassManager &pm = asyncExecutors[pmIndex][opInfo.passManagerIdx];
840850
LogicalResult pipelineResult = runPipeline(
841-
pm, opInfo.op, opInfo.am, verifyPasses,
851+
pm, opInfo.op, opInfo.am, verifyPasses, emitErrorOnFailure,
842852
pm.impl->initializationGeneration, instrumentor, &parentInfo);
843853
if (failed(pipelineResult))
844854
hasFailure.store(true);
@@ -859,17 +869,21 @@ void OpToOpPassAdaptor::runOnOperationAsyncImpl(bool verifyPasses) {
859869
PassManager::PassManager(MLIRContext *ctx, StringRef operationName,
860870
Nesting nesting)
861871
: OpPassManager(operationName, nesting), context(ctx), passTiming(false),
862-
verifyPasses(true) {}
872+
verifyPasses(true), emitErrorOnFailure(false) {}
863873

864874
PassManager::PassManager(OperationName operationName, Nesting nesting)
865875
: OpPassManager(operationName, nesting),
866876
context(operationName.getContext()), passTiming(false),
867-
verifyPasses(true) {}
877+
verifyPasses(true), emitErrorOnFailure(false) {}
868878

869879
PassManager::~PassManager() = default;
870880

871881
void PassManager::enableVerifier(bool enabled) { verifyPasses = enabled; }
872882

883+
void PassManager::enableErrorOnFailure(bool enabled) {
884+
emitErrorOnFailure = enabled;
885+
}
886+
873887
/// Run the passes within this manager on the provided operation.
874888
LogicalResult PassManager::run(Operation *op) {
875889
MLIRContext *context = getContext();
@@ -931,6 +945,7 @@ void PassManager::addInstrumentation(std::unique_ptr<PassInstrumentation> pi) {
931945

932946
LogicalResult PassManager::runPasses(Operation *op, AnalysisManager am) {
933947
return OpToOpPassAdaptor::runPipeline(*this, op, am, verifyPasses,
948+
emitErrorOnFailure,
934949
impl->initializationGeneration);
935950
}
936951

mlir/lib/Pass/PassDetail.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class OpToOpPassAdaptor
2929
OpToOpPassAdaptor(const OpToOpPassAdaptor &rhs) = default;
3030

3131
/// Run the held pipeline over all operations.
32-
void runOnOperation(bool verifyPasses);
32+
void runOnOperation(bool verifyPasses, bool emitErrorOnFailure);
3333
void runOnOperation() override;
3434

3535
/// Try to merge the current pass adaptor into 'rhs'. This will try to append
@@ -60,25 +60,29 @@ class OpToOpPassAdaptor
6060

6161
private:
6262
/// Run this pass adaptor synchronously.
63-
void runOnOperationImpl(bool verifyPasses);
63+
void runOnOperationImpl(bool verifyPasses, bool emitErrorOnFailure);
6464

6565
/// Run this pass adaptor asynchronously.
66-
void runOnOperationAsyncImpl(bool verifyPasses);
66+
void runOnOperationAsyncImpl(bool verifyPasses, bool emitErrorOnFailure);
6767

6868
/// Run the given operation and analysis manager on a single pass.
6969
/// `parentInitGeneration` is the initialization generation of the parent pass
7070
/// manager, and is used to initialize any dynamic pass pipelines run by the
71-
/// given pass.
71+
/// given pass. If `emitErrorOnFailure` is set, when a pass in
72+
/// the pipeline fails its name will be emitted in an error.
7273
static LogicalResult run(Pass *pass, Operation *op, AnalysisManager am,
73-
bool verifyPasses, unsigned parentInitGeneration);
74+
bool verifyPasses, bool emitErrorOnFailure,
75+
unsigned parentInitGeneration);
7476

7577
/// Run the given operation and analysis manager on a provided op pass
7678
/// manager. `parentInitGeneration` is the initialization generation of the
7779
/// parent pass manager, and is used to initialize any dynamic pass pipelines
78-
/// run by the given passes.
80+
/// run by the given passes. If `emitErrorOnFailure` is set, when a pass in
81+
/// the pipeline fails its name will be emitted in an error.
7982
static LogicalResult runPipeline(
8083
OpPassManager &pm, Operation *op, AnalysisManager am, bool verifyPasses,
81-
unsigned parentInitGeneration, PassInstrumentor *instrumentor = nullptr,
84+
bool emitErrorOnFailure, unsigned parentInitGeneration,
85+
PassInstrumentor *instrumentor = nullptr,
8286
const PassInstrumentation::PipelineParentInfo *parentInfo = nullptr);
8387

8488
/// A set of adaptors to run.

mlir/lib/Tools/mlir-opt/MlirOptMain.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
182182
cl::desc("Run the verifier after each transformation pass"),
183183
cl::location(verifyPassesFlag), cl::init(true));
184184

185+
static cl::opt<bool, /*ExternalStorage=*/true> emitPassErrorOnFailure(
186+
"emit-pass-error-on-failure",
187+
cl::desc("Emit an error with the pass name when a pass fails"),
188+
cl::location(emitErrorOnPassFailureFlag), cl::init(false));
189+
185190
static cl::opt<bool, /*ExternalStorage=*/true> disableVerifyOnParsing(
186191
"mlir-very-unsafe-disable-verifier-on-parsing",
187192
cl::desc("Disable the verifier on parsing (very unsafe)"),
@@ -465,6 +470,7 @@ performActions(raw_ostream &os,
465470
// Prepare the pass manager, applying command-line and reproducer options.
466471
PassManager pm(op.get()->getName(), PassManager::Nesting::Implicit);
467472
pm.enableVerifier(config.shouldVerifyPasses());
473+
pm.enableErrorOnFailure(config.shouldEmitErrorOnPassFailure());
468474
if (failed(applyPassManagerCLOptions(pm)))
469475
return failure();
470476
pm.enableTiming(timing);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(test-pass-failure{gen-diagnostics}))' -emit-pass-error-on-failure -verify-diagnostics=only-expected
2+
3+
// expected-error@+2 {{failed to run pass}}
4+
// expected-error@+1 {{illegal operation}}
5+
func.func @TestAlwaysIllegalOperationPass1() {
6+
return
7+
}

0 commit comments

Comments
 (0)