forked from OSchip/llvm-project
Add ::printAsTextualPipeline to Pass and OpPassManager.
Allow printing out pipelines in a format that is as close as possible to the textual pass pipeline format. Individual passes can override the print function in order to format any options that may have been used to construct that pass. PiperOrigin-RevId: 273813627
This commit is contained in:
parent
35bb732032
commit
ae6946ec11
|
@ -427,6 +427,11 @@ Can also be specified as (via the `-pass-pipeline` flag):
|
|||
$ mlir-opt foo.mlir -pass-pipeline='func(cse, canonicalize), lower-to-llvm'
|
||||
```
|
||||
|
||||
In order to support round-tripping your pass to the textual representation using
|
||||
`OpPassManager::printAsTextualPipeline(raw_ostream&)`, override
|
||||
`Pass::printAsTextualPipeline(raw_ostream&)` to format your pass-name and
|
||||
options in the format described above.
|
||||
|
||||
### Instance Specific Pass Options
|
||||
|
||||
Options may be specified for a parametric pass. Individual options are defined
|
||||
|
|
|
@ -69,6 +69,13 @@ public:
|
|||
/// this is a generic OperationPass.
|
||||
llvm::Optional<StringRef> getOpName() const { return opName; }
|
||||
|
||||
/// Prints out the pass in the textual representation of pipelines. If this is
|
||||
/// an adaptor pass, print with the op_name(sub_pass,...) format.
|
||||
/// Note: The default implementation uses the class name and does not respect
|
||||
/// options used to construct the pass. Override this method to allow for your
|
||||
/// pass to be to be round-trippable to the textual format.
|
||||
virtual void printAsTextualPipeline(raw_ostream &os);
|
||||
|
||||
protected:
|
||||
explicit Pass(const PassID *passID,
|
||||
llvm::Optional<StringRef> opName = llvm::None)
|
||||
|
|
|
@ -80,6 +80,12 @@ public:
|
|||
/// Returns the internal implementation instance.
|
||||
detail::OpPassManagerImpl &getImpl();
|
||||
|
||||
/// Prints out the passes of the pass mangager as the textual representation
|
||||
/// of pipelines.
|
||||
/// 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);
|
||||
|
||||
private:
|
||||
OpPassManager(OperationName name, bool disableThreads, bool verifyPasses);
|
||||
|
||||
|
|
|
@ -42,6 +42,21 @@ using namespace mlir::detail;
|
|||
/// single .o file.
|
||||
void Pass::anchor() {}
|
||||
|
||||
/// Prints out the pass in the textual representation of pipelines. If this is
|
||||
/// an adaptor pass, print with the op_name(sub_pass,...) format.
|
||||
void Pass::printAsTextualPipeline(raw_ostream &os) {
|
||||
// Special case for adaptors to use the 'op_name(sub_passes)' format.
|
||||
if (auto *adaptor = getAdaptorPassBase(this)) {
|
||||
interleaveComma(adaptor->getPassManagers(), os, [&](OpPassManager &pm) {
|
||||
os << pm.getOpName() << "(";
|
||||
pm.printAsTextualPipeline(os);
|
||||
os << ")";
|
||||
});
|
||||
} else {
|
||||
os << getName();
|
||||
}
|
||||
}
|
||||
|
||||
/// Forwarding function to execute this pass.
|
||||
LogicalResult Pass::run(Operation *op, AnalysisManager am) {
|
||||
passState.emplace(op, am);
|
||||
|
@ -254,6 +269,14 @@ MLIRContext *OpPassManager::getContext() const {
|
|||
/// Return the operation name that this pass manager operates on.
|
||||
const OperationName &OpPassManager::getOpName() const { return impl->name; }
|
||||
|
||||
/// Prints out the passes of the pass mangager as the textual representation
|
||||
/// of pipelines.
|
||||
void OpPassManager::printAsTextualPipeline(raw_ostream &os) {
|
||||
interleaveComma(impl->passes, os, [&](const std::unique_ptr<Pass> &pass) {
|
||||
pass->printAsTextualPipeline(os);
|
||||
});
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpToOpPassAdaptor
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
// RUN: not mlir-opt %s -pass-pipeline='module(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: not mlir-opt %s -pass-pipeline='func(test-options-pass{list=1,2,3,4 list=5 string=value1 string=value2})' 2>&1 | FileCheck --check-prefix=CHECK_ERROR_5 %s
|
||||
// RUN: mlir-opt %s -pass-pipeline='func(test-options-pass{string-list=a list=1,2,3,4 string-list=b,c list=5 string-list=d string=some_value})' 2>&1 | FileCheck --check-prefix=CHECK_1 %s
|
||||
// RUN: mlir-opt %s -test-options-pass-pipeline='list=1 string-list=a,b' 2>&1 | FileCheck --check-prefix=CHECK_2 %s
|
||||
// RUN: mlir-opt %s -pass-pipeline='module(test-options-pass{list=3}, test-options-pass{list=1,2,3,4})' 2>&1 | FileCheck --check-prefix=CHECK_3 %s
|
||||
// RUN: mlir-opt %s -verify-each=false -pass-pipeline='func(test-options-pass{string-list=a list=1,2,3,4 string-list=b,c list=5 string-list=d string=some_value})' -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='module(test-options-pass{list=3}, test-options-pass{list=1,2,3,4})' -test-dump-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
|
||||
|
@ -15,5 +15,4 @@
|
|||
|
||||
// CHECK_1: test-options-pass{list=1,2,3,4,5 string-list=a,b,c,d string=some_value}
|
||||
// CHECK_2: test-options-pass{list=1 string-list=a,b}
|
||||
// CHECK_3: test-options-pass{list=3}
|
||||
// CHECK_3-NEXT: test-options-pass{list=1,2,3,4}
|
||||
// CHECK_3: module(func(test-options-pass{list=3}), func(test-options-pass{list=1,2,3,4}))
|
||||
|
|
|
@ -45,13 +45,9 @@ public:
|
|||
stringOption = options.stringOption;
|
||||
stringListOption.assign(options.stringListOption.begin(),
|
||||
options.stringListOption.end());
|
||||
// Print out a debug representation of the pass in order to allow FileCheck
|
||||
// testing of options parsing.
|
||||
print(llvm::errs());
|
||||
llvm::errs() << "\n";
|
||||
}
|
||||
|
||||
void print(raw_ostream &os) {
|
||||
void printAsTextualPipeline(raw_ostream &os) final {
|
||||
os << "test-options-pass{";
|
||||
if (!listOption.empty()) {
|
||||
os << "list=";
|
||||
|
@ -108,6 +104,13 @@ static PassPipelineRegistration<>
|
|||
unusedTextual("test-textual-pm-nested-pipeline",
|
||||
"Test a nested pipeline in the pass manager",
|
||||
testNestedPipelineTextual);
|
||||
static PassPipelineRegistration<>
|
||||
unusedDump("test-dump-pipeline",
|
||||
"Dumps the pipeline build so far for debugging purposes",
|
||||
[](OpPassManager &pm) {
|
||||
pm.printAsTextualPipeline(llvm::errs());
|
||||
llvm::errs() << "\n";
|
||||
});
|
||||
|
||||
static PassPipelineRegistration<TestOptionsPass::Options>
|
||||
registerOptionsPassPipeline(
|
||||
|
|
Loading…
Reference in New Issue