forked from OSchip/llvm-project
[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:
parent
7e7f38f853
commit
e9cda7c5a0
|
@ -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_
|
||||
|
|
|
@ -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)};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue