diff --git a/mlir/include/mlir/Pass/Pass.h b/mlir/include/mlir/Pass/Pass.h index 9e8ba7158f1b3..16893c6db87b1 100644 --- a/mlir/include/mlir/Pass/Pass.h +++ b/mlir/include/mlir/Pass/Pass.h @@ -118,8 +118,9 @@ class Pass { function_ref errorHandler); /// Prints out the pass in the textual representation of pipelines. If this is - /// an adaptor pass, print its pass managers. - void printAsTextualPipeline(raw_ostream &os); + /// an adaptor pass, print its pass managers. When `pretty` is true, the + /// printed pipeline is formatted for readability. + void printAsTextualPipeline(raw_ostream &os, bool pretty = false); //===--------------------------------------------------------------------===// // Statistics diff --git a/mlir/include/mlir/Pass/PassManager.h b/mlir/include/mlir/Pass/PassManager.h index 2287b0a33f47d..6e59b0f32ac6f 100644 --- a/mlir/include/mlir/Pass/PassManager.h +++ b/mlir/include/mlir/Pass/PassManager.h @@ -140,10 +140,12 @@ class OpPassManager { detail::OpPassManagerImpl &getImpl(); /// Prints out the passes of the pass manager as the textual representation - /// of pipelines. + /// of pipelines. When `pretty` is true, the printed pipeline is formatted + /// for readability. + /// /// Note: The quality of the string representation depends entirely on the /// the correctness of per-pass overrides of Pass::printAsTextualPipeline. - void printAsTextualPipeline(raw_ostream &os) const; + void printAsTextualPipeline(raw_ostream &os, bool pretty = false) const; /// Raw dump of the pass manager to llvm::errs(). void dump(); diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp index e0e9b5f54042a..d1371d2b508f4 100644 --- a/mlir/lib/Pass/Pass.cpp +++ b/mlir/lib/Pass/Pass.cpp @@ -18,6 +18,7 @@ #include "mlir/IR/Threading.h" #include "mlir/IR/Verifier.h" #include "mlir/Support/FileUtilities.h" +#include "mlir/Support/IndentedOstream.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" @@ -80,14 +81,19 @@ void Pass::copyOptionValuesFrom(const Pass *other) { } /// Prints out the pass in the textual representation of pipelines. If this is -/// an adaptor pass, print its pass managers. -void Pass::printAsTextualPipeline(raw_ostream &os) { +/// an adaptor pass, print its pass managers. When `pretty` is true, the +/// printed pipeline is formatted for readability. +void Pass::printAsTextualPipeline(raw_ostream &os, bool pretty) { // Special case for adaptors to print its pass managers. if (auto *adaptor = dyn_cast(this)) { llvm::interleave( adaptor->getPassManagers(), - [&](OpPassManager &pm) { pm.printAsTextualPipeline(os); }, - [&] { os << ","; }); + [&](OpPassManager &pm) { pm.printAsTextualPipeline(os, pretty); }, + [&] { + os << ","; + if (pretty) + os << "\n"; + }); return; } // Otherwise, print the pass argument followed by its options. If the pass @@ -390,27 +396,51 @@ StringRef OpPassManager::getOpAnchorName() const { } /// Prints out the passes of the pass manager as the textual representation -/// of pipelines. +/// of pipelines. When `pretty` is true, the printed pipeline is formatted for +/// readability. void printAsTextualPipeline( - raw_ostream &os, StringRef anchorName, - const llvm::iterator_range &passes) { + raw_indented_ostream &os, StringRef anchorName, + const llvm::iterator_range &passes, + bool pretty = false) { os << anchorName << "("; + if (pretty) { + os << "\n"; + os.indent(); + } llvm::interleave( - passes, [&](mlir::Pass &pass) { pass.printAsTextualPipeline(os); }, - [&]() { os << ","; }); + passes, + [&](mlir::Pass &pass) { pass.printAsTextualPipeline(os, pretty); }, + [&]() { + os << ","; + if (pretty) + os << "\n"; + }); + if (pretty) { + os << "\n"; + os.unindent(); + } os << ")"; } -void OpPassManager::printAsTextualPipeline(raw_ostream &os) const { +void printAsTextualPipeline( + raw_ostream &os, StringRef anchorName, + const llvm::iterator_range &passes, + bool pretty) { + raw_indented_ostream indentedOS(os); + printAsTextualPipeline(indentedOS, anchorName, passes, pretty); +} +void OpPassManager::printAsTextualPipeline(raw_ostream &os, bool pretty) const { StringRef anchorName = getOpAnchorName(); + raw_indented_ostream indentedOS(os); ::printAsTextualPipeline( - os, anchorName, + indentedOS, anchorName, {MutableArrayRef>{impl->passes}.begin(), - MutableArrayRef>{impl->passes}.end()}); + MutableArrayRef>{impl->passes}.end()}, + pretty); } void OpPassManager::dump() { llvm::errs() << "Pass Manager with " << impl->passes.size() << " passes:\n"; - printAsTextualPipeline(llvm::errs()); + printAsTextualPipeline(llvm::errs(), /*pretty=*/true); llvm::errs() << "\n"; } @@ -466,7 +496,6 @@ llvm::hash_code OpPassManager::hash() { return hashCode; } - //===----------------------------------------------------------------------===// // OpToOpPassAdaptor //===----------------------------------------------------------------------===// @@ -871,7 +900,8 @@ LogicalResult PassManager::run(Operation *op) { // Initialize all of the passes within the pass manager with a new generation. llvm::hash_code newInitKey = context->getRegistryHash(); llvm::hash_code pipelineKey = hash(); - if (newInitKey != initializationKey || pipelineKey != pipelineInitializationKey) { + if (newInitKey != initializationKey || + pipelineKey != pipelineInitializationKey) { if (failed(initialize(context, impl->initializationGeneration + 1))) return failure(); initializationKey = newInitKey; diff --git a/mlir/lib/Pass/PassCrashRecovery.cpp b/mlir/lib/Pass/PassCrashRecovery.cpp index 8c6d865cb31dd..b048ff9462392 100644 --- a/mlir/lib/Pass/PassCrashRecovery.cpp +++ b/mlir/lib/Pass/PassCrashRecovery.cpp @@ -443,7 +443,8 @@ makeReproducerStreamFactory(StringRef outputFile) { void printAsTextualPipeline( raw_ostream &os, StringRef anchorName, - const llvm::iterator_range &passes); + const llvm::iterator_range &passes, + bool pretty = false); std::string mlir::makeReproducer( StringRef anchorName, diff --git a/mlir/test/Pass/pipeline-options-parsing.mlir b/mlir/test/Pass/pipeline-options-parsing.mlir index b8cd605a83a2b..9385d353faf95 100644 --- a/mlir/test/Pass/pipeline-options-parsing.mlir +++ b/mlir/test/Pass/pipeline-options-parsing.mlir @@ -38,11 +38,71 @@ // CHECK_1: test-options-pass{enum=zero list={1,2,3,4,5} string=nested_pipeline{arg1=10 arg2=" {} " arg3=true} string-list={a,b,c,d}} // CHECK_2: test-options-pass{enum=one list={1} string= string-list={a,b}} -// CHECK_3: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string= }))) -// CHECK_4: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string=foobar }))) -// CHECK_5: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string={foo bar baz} }))) -// CHECK_6: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string=foo"bar"baz }))) -// CHECK_7{LITERAL}: builtin.module(func.func(test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one list={2} string=bar },{enum=two list={3} string=baz }}})) -// CHECK_8{LITERAL}: builtin.module(func.func(test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one string=bar }}})) -// CHECK_9: builtin.module(func.func(test-options-pass{enum=zero string= string-list={}})) -// CHECK_10: builtin.module(func.func(test-options-pass{enum=zero string= string-list={,}})) + +// CHECK_3: builtin.module( +// CHECK_3-NEXT: builtin.module( +// CHECK_3-NEXT: func.func( +// CHECK_3-NEXT: test-options-pass{enum=zero list={3} string= } +// CHECK_3-NEXT: ), +// CHECK_3-NEXT: func.func( +// CHECK_3-NEXT: test-options-pass{enum=one list={1,2,3,4} string= } +// CHECK_3-NEXT: ) +// CHECK_3-NEXT: ) +// CHECK_3-NEXT: ) + +// CHECK_4: builtin.module( +// CHECK_4-NEXT: builtin.module( +// CHECK_4-NEXT: func.func( +// CHECK_4-NEXT: test-options-pass{enum=zero list={3} string= } +// CHECK_4-NEXT: ), +// CHECK_4-NEXT: func.func( +// CHECK_4-NEXT: test-options-pass{enum=one list={1,2,3,4} string=foobar } +// CHECK_4-NEXT: ) +// CHECK_4-NEXT: ) +// CHECK_4-NEXT: ) + +// CHECK_5: builtin.module( +// CHECK_5-NEXT: builtin.module( +// CHECK_5-NEXT: func.func( +// CHECK_5-NEXT: test-options-pass{enum=zero list={3} string= } +// CHECK_5-NEXT: ), +// CHECK_5-NEXT: func.func( +// CHECK_5-NEXT: test-options-pass{enum=one list={1,2,3,4} string={foo bar baz} } +// CHECK_5-NEXT: ) +// CHECK_5-NEXT: ) +// CHECK_5-NEXT: ) + +// CHECK_6: builtin.module( +// CHECK_6-NEXT: builtin.module( +// CHECK_6-NEXT: func.func( +// CHECK_6-NEXT: test-options-pass{enum=zero list={3} string= } +// CHECK_6-NEXT: ), +// CHECK_6-NEXT: func.func( +// CHECK_6-NEXT: test-options-pass{enum=one list={1,2,3,4} string=foo"bar"baz } +// CHECK_6-NEXT: ) +// CHECK_6-NEXT: ) +// CHECK_6-NEXT: ) + +// CHECK_7{LITERAL}: builtin.module( +// CHECK_7{LITERAL}-NEXT: func.func( +// CHECK_7{LITERAL}-NEXT: test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one list={2} string=bar },{enum=two list={3} string=baz }}} +// CHECK_7{LITERAL}-NEXT: ) +// CHECK_7{LITERAL}-NEXT: ) + +// CHECK_8{LITERAL}: builtin.module( +// CHECK_8{LITERAL}-NEXT: func.func( +// CHECK_8{LITERAL}-NEXT: test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one string=bar }}} +// CHECK_8{LITERAL}-NEXT: ) +// CHECK_8{LITERAL}-NEXT: ) + +// CHECK_9: builtin.module( +// CHECK_9-NEXT: func.func( +// CHECK_9-NEXT: test-options-pass{enum=zero string= string-list={}} +// CHECK_9-NEXT: ) +// CHECK_9-NEXT: ) + +// CHECK_10: builtin.module( +// CHECK_10-NEXT: func.func( +// CHECK_10-NEXT: test-options-pass{enum=zero string= string-list={,}} +// CHECK_10-NEXT: ) +// CHECK_10-NEXT: ) diff --git a/mlir/test/Pass/pipeline-parsing.mlir b/mlir/test/Pass/pipeline-parsing.mlir index f41553d2669f0..7f368c6df2af5 100644 --- a/mlir/test/Pass/pipeline-parsing.mlir +++ b/mlir/test/Pass/pipeline-parsing.mlir @@ -21,7 +21,9 @@ // CHECK_ERROR_7: can't run 'wrong-op' pass manager on 'builtin.module' op // RUN: mlir-opt %s -pass-pipeline='any(cse)' -dump-pass-pipeline 2>&1 | FileCheck %s -check-prefix=CHECK_ROUNDTRIP -// CHECK_ROUNDTRIP: any(cse) +// CHECK_ROUNDTRIP: any( +// CHECK_ROUNDTRIP-NEXT: cse +// CHECK_ROUNDTRIP-NEXT: ) func.func @foo() { return diff --git a/mlir/test/Pass/run-reproducer.mlir b/mlir/test/Pass/run-reproducer.mlir index bf3ab2dae2ff8..d2daceab163de 100644 --- a/mlir/test/Pass/run-reproducer.mlir +++ b/mlir/test/Pass/run-reproducer.mlir @@ -14,7 +14,12 @@ func.func @bar() { external_resources: { mlir_reproducer: { verify_each: true, - // CHECK: builtin.module(func.func(cse,canonicalize{ max-iterations=1 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=false})) + // CHECK: builtin.module( + // CHECK-NEXT: func.func( + // CHECK-NEXT: cse, + // CHECK-NEXT: canonicalize{ max-iterations=1 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=false} + // CHECK-NEXT: ) + // CHECK-NEXT: ) pipeline: "builtin.module(func.func(cse,canonicalize{max-iterations=1 max-num-rewrites=-1 region-simplify=normal top-down=false}))", disable_threading: true } diff --git a/mlir/test/Transforms/composite-pass.mlir b/mlir/test/Transforms/composite-pass.mlir index 75587edd5b96d..65764a96a4016 100644 --- a/mlir/test/Transforms/composite-pass.mlir +++ b/mlir/test/Transforms/composite-pass.mlir @@ -2,8 +2,9 @@ // RUN: mlir-opt %s --log-actions-to=- --composite-fixed-point-pass='name=TestCompositePass pipeline=any(canonicalize,cse)' -split-input-file | FileCheck %s // Ensure the composite pass correctly prints its options. -// PIPELINE: builtin.module(composite-fixed-point-pass{max-iterations=10 name=TestCompositePass -// PIPELINE-SAME: pipeline=canonicalize{ max-iterations=10 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=true},cse}) +// PIPELINE: builtin.module( +// PIPELINE-NEXT: composite-fixed-point-pass{max-iterations=10 name=TestCompositePass +// PIPELINE-SAME: pipeline=canonicalize{ max-iterations=10 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=true},cse} // CHECK-LABEL: running `TestCompositePass` // CHECK: running `Canonicalizer` diff --git a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir index 4f8638054206e..ef5fac49c6ce2 100644 --- a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir +++ b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir @@ -1,2 +1,4 @@ // RUN: mlir-opt %s -pass-pipeline="builtin.module(inline)" -dump-pass-pipeline 2>&1 | FileCheck %s -// CHECK: builtin.module(inline{default-pipeline=canonicalize inlining-threshold=4294967295 max-iterations=4 }) +// CHECK: builtin.module( +// CHECK-NEXT: inline{default-pipeline=canonicalize inlining-threshold=4294967295 max-iterations=4 } +// CHECK-NEXT: )