[mlir][Pass] Add a new PassNameCLParser specifically for parsing lists of pass names

This parser does not include the general `pass_pipeline` option, the pass pipeline entries, or the options of pass entries. This is useful for cases such as `print-ir-after` that just want the user to select specific pass types. This revision greatly reduces the amount of text in --help for several MLIR based tools.

Fixes PR#45495

Differential Revision: https://reviews.llvm.org/D92987
This commit is contained in:
River Riddle 2020-12-15 14:42:16 -08:00
parent 7e7f38f853
commit e9cda7c5a0
3 changed files with 83 additions and 15 deletions

View File

@ -246,6 +246,26 @@ private:
std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
};
/// This class implements a command-line parser spefically for MLIR pass names.
/// It registers a cl option with a given argument and description that accepts
/// a comma delimited list of pass names.
class PassNameCLParser {
public:
/// Construct a parser with the given command line description.
PassNameCLParser(StringRef arg, StringRef description);
~PassNameCLParser();
/// Returns true if this parser contains any valid options to add.
bool hasAnyOccurrences() const;
/// Returns true if the given pass registry entry was registered at the
/// top-level of the parser, i.e. not within an explicit textual pipeline.
bool contains(const PassRegistryEntry *entry) const;
private:
std::unique_ptr<detail::PassPipelineCLParserImpl> impl;
};
} // end namespace mlir
#endif // MLIR_PASS_PASSREGISTRY_H_

View File

@ -32,10 +32,10 @@ struct PassManagerOptions {
//===--------------------------------------------------------------------===//
// IR Printing
//===--------------------------------------------------------------------===//
PassPipelineCLParser printBefore{"print-ir-before",
"Print IR before specified passes"};
PassPipelineCLParser printAfter{"print-ir-after",
"Print IR after specified passes"};
PassNameCLParser printBefore{"print-ir-before",
"Print IR before specified passes"};
PassNameCLParser printAfter{"print-ir-after",
"Print IR after specified passes"};
llvm::cl::opt<bool> printBeforeAll{
"print-ir-before-all", llvm::cl::desc("Print IR before each pass"),
llvm::cl::init(false)};

View File

@ -543,6 +543,12 @@ struct PassNameParser : public llvm::cl::parser<PassArgData> {
size_t getOptionWidth(const llvm::cl::Option &opt) const override;
bool parse(llvm::cl::Option &opt, StringRef argName, StringRef arg,
PassArgData &value);
/// If true, this parser only parses entries that correspond to a concrete
/// pass registry entry, and does not add a `pass-pipeline` argument, does not
/// include the options for pass entries, and does not include pass pipelines
/// entries.
bool passNamesOnly = false;
};
} // namespace
@ -550,8 +556,10 @@ void PassNameParser::initialize() {
llvm::cl::parser<PassArgData>::initialize();
/// Add an entry for the textual pass pipeline option.
addLiteralOption(passPipelineArg, PassArgData(),
"A textual description of a pass pipeline to run");
if (!passNamesOnly) {
addLiteralOption(passPipelineArg, PassArgData(),
"A textual description of a pass pipeline to run");
}
/// Add the pass entries.
for (const auto &kv : *passRegistry) {
@ -559,14 +567,24 @@ void PassNameParser::initialize() {
kv.second.getPassDescription());
}
/// Add the pass pipeline entries.
for (const auto &kv : *passPipelineRegistry) {
addLiteralOption(kv.second.getPassArgument(), &kv.second,
kv.second.getPassDescription());
if (!passNamesOnly) {
for (const auto &kv : *passPipelineRegistry) {
addLiteralOption(kv.second.getPassArgument(), &kv.second,
kv.second.getPassDescription());
}
}
}
void PassNameParser::printOptionInfo(const llvm::cl::Option &opt,
size_t globalWidth) const {
// If this parser is just parsing pass names, print a simplified option
// string.
if (passNamesOnly) {
llvm::outs() << " --" << opt.ArgStr << "=<pass-arg>";
opt.printHelpStr(opt.HelpStr, globalWidth, opt.ArgStr.size() + 18);
return;
}
// Print the information for the top-level option.
if (opt.hasArgStr()) {
llvm::outs() << " --" << opt.ArgStr;
@ -635,11 +653,21 @@ bool PassNameParser::parse(llvm::cl::Option &opt, StringRef argName,
namespace mlir {
namespace detail {
struct PassPipelineCLParserImpl {
PassPipelineCLParserImpl(StringRef arg, StringRef description)
PassPipelineCLParserImpl(StringRef arg, StringRef description,
bool passNamesOnly)
: passList(arg, llvm::cl::desc(description)) {
passList.getParser().passNamesOnly = passNamesOnly;
passList.setValueExpectedFlag(llvm::cl::ValueExpected::ValueOptional);
}
/// Returns true if the given pass registry entry was registered at the
/// top-level of the parser, i.e. not within an explicit textual pipeline.
bool contains(const PassRegistryEntry *entry) const {
return llvm::any_of(passList, [&](const PassArgData &data) {
return data.registryEntry == entry;
});
}
/// The set of passes and pass pipelines to run.
llvm::cl::list<PassArgData, bool, PassNameParser> passList;
};
@ -648,8 +676,8 @@ struct PassPipelineCLParserImpl {
/// Construct a pass pipeline parser with the given command line description.
PassPipelineCLParser::PassPipelineCLParser(StringRef arg, StringRef description)
: impl(std::make_unique<detail::PassPipelineCLParserImpl>(arg,
description)) {}
: impl(std::make_unique<detail::PassPipelineCLParserImpl>(
arg, description, /*passNamesOnly=*/false)) {}
PassPipelineCLParser::~PassPipelineCLParser() {}
/// Returns true if this parser contains any valid options to add.
@ -660,9 +688,7 @@ bool PassPipelineCLParser::hasAnyOccurrences() const {
/// Returns true if the given pass registry entry was registered at the
/// top-level of the parser, i.e. not within an explicit textual pipeline.
bool PassPipelineCLParser::contains(const PassRegistryEntry *entry) const {
return llvm::any_of(impl->passList, [&](const PassArgData &data) {
return data.registryEntry == entry;
});
return impl->contains(entry);
}
/// Adds the passes defined by this parser entry to the given pass manager.
@ -685,3 +711,25 @@ LogicalResult PassPipelineCLParser::addToPipeline(
}
return success();
}
//===----------------------------------------------------------------------===//
// PassNameCLParser
/// Construct a pass pipeline parser with the given command line description.
PassNameCLParser::PassNameCLParser(StringRef arg, StringRef description)
: impl(std::make_unique<detail::PassPipelineCLParserImpl>(
arg, description, /*passNamesOnly=*/true)) {
impl->passList.setMiscFlag(llvm::cl::CommaSeparated);
}
PassNameCLParser::~PassNameCLParser() {}
/// Returns true if this parser contains any valid options to add.
bool PassNameCLParser::hasAnyOccurrences() const {
return impl->passList.getNumOccurrences() != 0;
}
/// Returns true if the given pass registry entry was registered at the
/// top-level of the parser, i.e. not within an explicit textual pipeline.
bool PassNameCLParser::contains(const PassRegistryEntry *entry) const {
return impl->contains(entry);
}