forked from OSchip/llvm-project
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:
parent
d42ef78a75
commit
50efe0fc85
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()))
|
||||
|
|
Loading…
Reference in New Issue