diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h --- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h +++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h @@ -53,12 +53,15 @@ /// - emitBytecode will generate bytecode output instead of text. /// - implicitModule will enable implicit addition of a top-level /// 'builtin.module' if one doesn't already exist. -LogicalResult MlirOptMain( - llvm::raw_ostream &outputStream, std::unique_ptr buffer, - const PassPipelineCLParser &passPipeline, DialectRegistry ®istry, - bool splitInputFile, bool verifyDiagnostics, bool verifyPasses, - bool allowUnregisteredDialects, bool preloadDialectsInContext = false, - bool emitBytecode = false, bool implicitModule = false); +/// - dumpPassPipeline will dump the pipeline being run to stderr +LogicalResult +MlirOptMain(llvm::raw_ostream &outputStream, + std::unique_ptr buffer, + const PassPipelineCLParser &passPipeline, DialectRegistry ®istry, + bool splitInputFile, bool verifyDiagnostics, bool verifyPasses, + bool allowUnregisteredDialects, + bool preloadDialectsInContext = false, bool emitBytecode = false, + bool implicitModule = false, bool dumpPassPipeline = false); /// Support a callback to setup the pass manager. /// - passManagerSetupFn is the callback invoked to setup the pass manager to diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp --- a/mlir/lib/Pass/Pass.cpp +++ b/mlir/lib/Pass/Pass.cpp @@ -365,9 +365,9 @@ } void OpPassManager::dump() { - llvm::errs() << "Pass Manager with " << impl->passes.size() << " passes: "; + llvm::errs() << "Pass Manager with " << impl->passes.size() << " passes:\n"; printAsTextualPipeline(llvm::errs()); - llvm::errs() << "\n"; + llvm::errs() << "\n\n"; } static void registerDialectsForPipeline(const OpPassManager &pm, diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -187,20 +187,22 @@ splitInputFile, /*insertMarkerInOutput=*/true); } -LogicalResult mlir::MlirOptMain(raw_ostream &outputStream, - std::unique_ptr buffer, - const PassPipelineCLParser &passPipeline, - DialectRegistry ®istry, bool splitInputFile, - bool verifyDiagnostics, bool verifyPasses, - bool allowUnregisteredDialects, - bool preloadDialectsInContext, - bool emitBytecode, bool implicitModule) { +LogicalResult mlir::MlirOptMain( + raw_ostream &outputStream, std::unique_ptr buffer, + const PassPipelineCLParser &passPipeline, DialectRegistry ®istry, + bool splitInputFile, bool verifyDiagnostics, bool verifyPasses, + bool allowUnregisteredDialects, bool preloadDialectsInContext, + bool emitBytecode, bool implicitModule, bool dumpPassPipeline) { auto passManagerSetupFn = [&](PassManager &pm) { auto errorHandler = [&](const Twine &msg) { emitError(UnknownLoc::get(pm.getContext())) << msg; return failure(); }; - return passPipeline.addToPipeline(pm, errorHandler); + if (failed(passPipeline.addToPipeline(pm, errorHandler))) + return failure(); + if (dumpPassPipeline) + pm.dump(); + return success(); }; return MlirOptMain(outputStream, std::move(buffer), passManagerSetupFn, registry, splitInputFile, verifyDiagnostics, verifyPasses, @@ -253,6 +255,10 @@ "Disable implicit addition of a top-level module op during parsing"), cl::init(false)}; + static cl::opt dumpPassPipeline{ + "dump-pass-pipeline", cl::desc("Print the pipeline that will be run"), + cl::init(false)}; + InitLLVM y(argc, argv); // Register any command line options. @@ -298,7 +304,8 @@ if (failed(MlirOptMain(output->os(), std::move(file), passPipeline, registry, splitInputFile, verifyDiagnostics, verifyPasses, allowUnregisteredDialects, preloadDialectsInContext, - emitBytecode, /*implicitModule=*/!noImplicitModule))) + emitBytecode, /*implicitModule=*/!noImplicitModule, + dumpPassPipeline))) return failure(); // Keep the output file if the invocation of MlirOptMain was successful. diff --git a/mlir/test/Pass/pipeline-options-parsing.mlir b/mlir/test/Pass/pipeline-options-parsing.mlir --- a/mlir/test/Pass/pipeline-options-parsing.mlir +++ b/mlir/test/Pass/pipeline-options-parsing.mlir @@ -3,9 +3,9 @@ // RUN: not mlir-opt %s -pass-pipeline='builtin.module(func.func(test-options-pass{list=3}), test-module-pass{invalid-option=3})' 2>&1 | FileCheck --check-prefix=CHECK_ERROR_3 %s // RUN: not mlir-opt %s -pass-pipeline='test-options-pass{list=3 list=notaninteger}' 2>&1 | FileCheck --check-prefix=CHECK_ERROR_4 %s // RUN: mlir-opt %s -pass-pipeline='func.func(test-options-pass{list=1,2,3,4 list=5 string=value1 string=value2})' -// RUN: mlir-opt %s -verify-each=false -pass-pipeline='func.func(test-options-pass{string-list=a list=1,2,3,4 string-list=b,c list=5 string-list=d string=nested_pipeline{arg1=10 arg2=" {} " arg3=true}})' -test-dump-pipeline 2>&1 | FileCheck --check-prefix=CHECK_1 %s -// RUN: mlir-opt %s -verify-each=false -test-options-pass-pipeline='list=1 string-list=a,b' -test-dump-pipeline 2>&1 | FileCheck --check-prefix=CHECK_2 %s -// RUN: mlir-opt %s -verify-each=false -pass-pipeline='builtin.module(func.func(test-options-pass{list=3}), func.func(test-options-pass{list=1,2,3,4}))' -test-dump-pipeline 2>&1 | FileCheck --check-prefix=CHECK_3 %s +// RUN: mlir-opt %s -verify-each=false -pass-pipeline='func.func(test-options-pass{string-list=a list=1,2,3,4 string-list=b,c list=5 string-list=d string=nested_pipeline{arg1=10 arg2=" {} " arg3=true}})' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_1 %s +// RUN: mlir-opt %s -verify-each=false -test-options-pass-pipeline='list=1 string-list=a,b' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_2 %s +// RUN: mlir-opt %s -verify-each=false -pass-pipeline='builtin.module(func.func(test-options-pass{list=3}), func.func(test-options-pass{list=1,2,3,4}))' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_3 %s // CHECK_ERROR_1: missing closing '}' while processing pass options // CHECK_ERROR_2: no such option test-option 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 @@ -228,13 +228,6 @@ PassPipelineRegistration<>("test-textual-pm-nested-pipeline", "Test a nested pipeline in the pass manager", testNestedPipelineTextual); - PassPipelineRegistration<>( - "test-dump-pipeline", - "Dumps the pipeline build so far for debugging purposes", - [](OpPassManager &pm) { - pm.printAsTextualPipeline(llvm::errs()); - llvm::errs() << "\n"; - }); PassPipelineRegistration registerOptionsPassPipeline(