Add a 'verifyPasses' flag to the PassManager that specifies if the IR should be verified after each pass. This also adds a "verify-each" flag to mlir-opt to optionally disable running the verifier after each pass.

PiperOrigin-RevId: 236703760
This commit is contained in:
River Riddle 2019-03-04 12:33:13 -08:00 committed by jpienaar
parent d42ef78a75
commit 50efe0fc85
3 changed files with 46 additions and 17 deletions

View File

@ -34,7 +34,8 @@ class ModulePassExecutor;
/// The main pass manager and pipeline builder.
class PassManager {
public:
PassManager();
// If verifyPasses is true, the verifier is run after each pass.
PassManager(bool verifyPasses = true);
~PassManager();
/// Add an opaque pass pointer to the current manager. This takes ownership
@ -61,6 +62,9 @@ private:
/// The top level module pass executor.
std::unique_ptr<detail::ModulePassExecutor> mpe;
/// Flag that specifies if the IR should be verified after each pass has run.
bool verifyPasses;
};
} // end namespace mlir

View File

@ -144,27 +144,20 @@ private:
/// Run all of the passes in this manager over the current function.
bool detail::FunctionPassExecutor::run(Function *function,
FunctionAnalysisManager &fam) {
for (auto &pass : passes) {
/// Create an execution state for this pass.
// Run each of the held passes.
for (auto &pass : passes)
if (!pass->run(function, fam))
return false;
// TODO: This should be opt-out and handled separately.
if (function->verify())
return false;
}
return true;
}
/// Run all of the passes in this manager over the current module.
bool detail::ModulePassExecutor::run(Module *module,
ModuleAnalysisManager &mam) {
for (auto &pass : passes) {
// Run each of the held passes.
for (auto &pass : passes)
if (!pass->run(module, mam))
return false;
// TODO: This should be opt-out and handled separately.
if (module->verify())
return false;
}
return true;
}
@ -224,7 +217,28 @@ void ModuleToFunctionPassAdaptor::runOnModule() {
// PassManager
//===----------------------------------------------------------------------===//
PassManager::PassManager() : mpe(new ModulePassExecutor()) {}
namespace {
/// Pass to verify a function and signal failure if necessary.
class FunctionVerifier : public FunctionPass<FunctionVerifier> {
void runOnFunction() {
if (getFunction().verify())
signalPassFailure();
markAllAnalysesPreserved();
}
};
/// Pass to verify a module and signal failure if necessary.
class ModuleVerifier : public ModulePass<ModuleVerifier> {
void runOnModule() {
if (getModule().verify())
signalPassFailure();
markAllAnalysesPreserved();
}
};
} // end anonymous namespace
PassManager::PassManager(bool verifyPasses)
: mpe(new ModulePassExecutor()), verifyPasses(verifyPasses) {}
PassManager::~PassManager() {}
@ -246,6 +260,10 @@ void PassManager::addPass(Pass *pass) {
void PassManager::addPass(ModulePassBase *pass) {
nestedExecutorStack.clear();
mpe->addPass(pass);
// Add a verifier run if requested.
if (verifyPasses)
mpe->addPass(new ModuleVerifier());
}
/// Add a function pass to the current manager. This takes ownership over the
@ -256,7 +274,7 @@ void PassManager::addPass(FunctionPassBase *pass) {
if (nestedExecutorStack.empty()) {
/// Create an executor adaptor for this pass.
auto *adaptor = new ModuleToFunctionPassAdaptor();
mpe->addPass(adaptor);
addPass(adaptor);
/// Add the executor to the stack.
fpe = &adaptor->getFunctionExecutor();
@ -265,6 +283,10 @@ void PassManager::addPass(FunctionPassBase *pass) {
fpe = cast<detail::FunctionPassExecutor>(nestedExecutorStack.back());
}
fpe->addPass(pass);
// Add a verifier run if requested.
if (verifyPasses)
fpe->addPass(new FunctionVerifier());
}
/// Run the passes within this manager on the provided module.

View File

@ -68,6 +68,11 @@ static cl::opt<bool>
"expected-* lines on the corresponding line"),
cl::init(false));
static cl::opt<bool>
verifyPasses("verify-each",
cl::desc("Run the verifier after each transformation pass"),
cl::init(true));
static std::vector<const mlir::PassRegistryEntry *> *passList;
enum OptResult { OptSuccess, OptFailure };
@ -126,9 +131,7 @@ static OptResult performActions(SourceMgr &sourceMgr, MLIRContext *context) {
return OptFailure;
// Run each of the passes that were selected.
// TODO(riverriddle) Make sure that the verifer is run after each pass when it
// is no longer run by default within the PassManager.
PassManager pm;
PassManager pm(verifyPasses);
for (const auto *passEntry : *passList)
passEntry->addToPipeline(pm);
if (!pm.run(module.get()))