diff --git a/mlir/lib/Pass/IRPrinting.cpp b/mlir/lib/Pass/IRPrinting.cpp --- a/mlir/lib/Pass/IRPrinting.cpp +++ b/mlir/lib/Pass/IRPrinting.cpp @@ -170,8 +170,7 @@ config->printAfterIfEnabled(pass, op, [&](raw_ostream &out) { out << formatv("// -----// IR Dump After {0} Failed", pass->getName()); - printIR(op, config->shouldPrintAtModuleScope(), out, - OpPrintingFlags().printGenericOpForm()); + printIR(op, config->shouldPrintAtModuleScope(), out, OpPrintingFlags()); out << "\n\n"; }); } diff --git a/mlir/test/Pass/invalid-ir-print-after-failure.mlir b/mlir/test/Pass/invalid-ir-print-after-failure.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Pass/invalid-ir-print-after-failure.mlir @@ -0,0 +1,12 @@ +// RUN: not mlir-opt %s -pass-pipeline='func.func(test-pass-create-invalid-ir{emit-invalid-ir=true signal-pass-failure=true})' -mlir-print-ir-after-failure 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID +// RUN: not mlir-opt %s -pass-pipeline='func.func(test-pass-create-invalid-ir{emit-invalid-ir=true signal-pass-failure=false})' -mlir-print-ir-after-failure 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID +// RUN: not mlir-opt %s -pass-pipeline='func.func(test-pass-create-invalid-ir{emit-invalid-ir=false signal-pass-failure=true})' -mlir-print-ir-after-failure 2>&1 | FileCheck %s --check-prefix=CHECK-VALID +// RUN: mlir-opt %s -pass-pipeline='func.func(test-pass-create-invalid-ir{emit-invalid-ir=false signal-pass-failure=false})' -mlir-print-ir-after-failure 2>&1 | FileCheck %s --check-prefix=CHECK-VALID + +// Test whether we print generically or not on pass failure, depending on whether there is invalid IR or not. + +// CHECK-VALID: func @TestCreateInvalidCallInPass +// CHECK-INVALID: "func.func" +func @TestCreateInvalidCallInPass() { + return + } diff --git a/mlir/test/Pass/ir-printing.mlir b/mlir/test/Pass/ir-printing.mlir --- a/mlir/test/Pass/ir-printing.mlir +++ b/mlir/test/Pass/ir-printing.mlir @@ -4,7 +4,7 @@ // RUN: mlir-opt %s -mlir-disable-threading=true -pass-pipeline='func.func(cse,canonicalize)' -mlir-print-ir-after-all -o /dev/null 2>&1 | FileCheck -check-prefix=AFTER_ALL %s // RUN: mlir-opt %s -mlir-disable-threading=true -pass-pipeline='func.func(cse,canonicalize)' -mlir-print-ir-before=cse -mlir-print-ir-module-scope -o /dev/null 2>&1 | FileCheck -check-prefix=BEFORE_MODULE %s // RUN: mlir-opt %s -mlir-disable-threading=true -pass-pipeline='func.func(cse,cse)' -mlir-print-ir-after-all -mlir-print-ir-after-change -o /dev/null 2>&1 | FileCheck -check-prefix=AFTER_ALL_CHANGE %s -// RUN: not mlir-opt %s -mlir-disable-threading=true -pass-pipeline='func.func(cse,test-pass-failure)' -mlir-print-ir-after-failure -o /dev/null 2>&1 | FileCheck -check-prefix=AFTER_FAILURE %s +// RUN: not mlir-opt %s -mlir-disable-threading=true -pass-pipeline='func.func(cse,test-pass-failure)' -mlir-print-ir-after-failure -o /dev/null 2>&1 | FileCheck -check-prefix=AFTER_FAILURE_CUSTOM %s func @foo() { %0 = arith.constant 0 : i32 @@ -62,5 +62,6 @@ // We expect that only 'foo' changed during CSE, and the second run of CSE did // nothing. -// AFTER_FAILURE-NOT: // -----// IR Dump After{{.*}}CSE -// AFTER_FAILURE: // -----// IR Dump After{{.*}}TestFailurePass Failed //----- // +// AFTER_FAILURE_CUSTOM-NOT: // -----// IR Dump After{{.*}}CSE +// AFTER_FAILURE_CUSTOM: // -----// IR Dump After{{.*}}TestFailurePass Failed //----- // +// AFTER_FAILURE_CUSTOM: func @foo() diff --git a/mlir/test/lib/Pass/TestPassManager.cpp b/mlir/test/lib/Pass/TestPassManager.cpp --- a/mlir/test/lib/Pass/TestPassManager.cpp +++ b/mlir/test/lib/Pass/TestPassManager.cpp @@ -131,6 +131,37 @@ } }; +/// A test pass that creates an invalid operation in a function body. +struct TestInvalidIRPass + : public PassWrapper> { + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestInvalidIRPass) + + TestInvalidIRPass() = default; + TestInvalidIRPass(const TestInvalidIRPass &other) {} + + StringRef getArgument() const final { return "test-pass-create-invalid-ir"; } + StringRef getDescription() const final { + return "Test pass that add an invalid operation in a function body"; + } + void getDependentDialects(DialectRegistry ®istry) const final { + registry.insert(); + } + void runOnOperation() final { + if (signalFailure) + signalPassFailure(); + if (!emitInvalidIR) + return; + OpBuilder b(getOperation().getBody()); + OperationState state(b.getUnknownLoc(), "test.any_attr_of_i32_str"); + b.create(state); + } + Option signalFailure{*this, "signal-pass-failure", + llvm::cl::desc("Trigger a pass failure")}; + Option emitInvalidIR{*this, "emit-invalid-ir", llvm::cl::init(true), + llvm::cl::desc("Emit invalid IR")}; +}; + /// A test pass that contains a statistic. struct TestStatisticPass : public PassWrapper> { @@ -180,6 +211,7 @@ PassRegistration(); PassRegistration(); PassRegistration(); + PassRegistration(); PassRegistration();