[llvm-dev] Understanding on-the-fly passes (Take 2)
David Greene via llvm-dev
llvm-dev at lists.llvm.org
Tue Mar 26 13:48:41 PDT 2019
Apologies for the earlier aborted e-mail. I hit a keyboard shortcut by
mistake. :)
I'm seeing some odd behavior with a ModulePass I'm developing. In order
for it to work with both the legacy and new pass managers, I've
abstracted away the code to get the passes it depends on:
// Legacy pass.
bool MyPass::runOnModule(Module &M) override {
auto DominatorGetter = [this] (Function &F) -> DominatorTree & {
return this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
};
auto PostDominatorGetter = [this] (Function &F) -> PostDominatorTree & {
return this->
getAnalysis<PostDominatorTreeWrapperPass>(F).getPostDomTree();
};
auto LoopInfoGetter = [this] (Function &F) -> LoopInfo & {
return this->getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
};
auto SCEVGetter = [this] (Function &F) -> ScalarEvolution & {
return this->getAnalysis<ScalarEvolutionWrapperPass>(F).getSE();
};
auto AssumptionCacheGetter = [this] (Function &F) ->
AssumptionCache & {
return
this->getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
};
auto OREGetter = [this] (Function &F) -> OptimizationRemarkEmitter & {
return this->
getAnalysis<OptimizationRemarkEmitterWrapperPass>(F).getORE();
};
doTheWork(M,
DominatorGetter,
PostDominatorGetter,
LoopInfoGetter,
SCEVGetter,
AssumptionCacheGetter,
OREGetter);
return false;
}
// New pass.
PreservedAnalyses
MyPass::run(Module &M, ModuleAnalysisManager &AM) {
auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
auto DominatorGetter = [&FAM] (Function &F) -> DominatorTree & {
return FAM.getResult<DominatorTreeAnalysis>(F);
};
auto PostDominatorGetter = [&FAM] (Function &F) -> PostDominatorTree & {
return FAM.getResult<PostDominatorTreeAnalysis>(F);
};
auto LoopInfoGetter = [&FAM] (Function &F) -> LoopInfo & {
return FAM.getResult<LoopAnalysis>(F);
};
auto SCEVGetter = [&FAM] (Function &F) -> ScalarEvolution & {
return FAM.getResult<ScalarEvolutionAnalysis>(F);
};
auto AssumptionCacheGetter = [&FAM] (Function &F) -> AssumptionCache & {
return FAM.getResult<AssumptionAnalysis>(F);
};
auto OREGetter = [&FAM] (Function &F) -> OptimizationRemarkEmitter & {
return FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
};
doTheWork(M,
DominatorGetter,
PostDominatorGetter,
LoopInfoGetter,
SCEVGetter,
AssumptionCacheGetter,
OREGetter);
return PreservedAnalyses::all();
}
template<typename D,
typename P,
typename L,
typename S,
typename A,
typename O>
bool doTheWork(Module &M,
D &DominatorGetter,
P &PostDominatorGetter,
L &LoopInfoGetter,
S &SCEVGetter,
A &AssumptionCacheGetter,
O &OREGetter) {
auto &FirstORE = OREGetter(getFirstDefinedFunction(M));
// Do some checking to see if doing the work makes sense and emit
// messages with FirstORE.
// Ok, everything ok, actually do the work.
for (auto &F : M) {
if (!F.isDeclaration()) {
auto &DT = DominatorGetter(F);
auto &PDT = PostDominatorGetter(F);
auto &LI = LoopInfoGetter(F);
auto &SE = SCEVGetter(F);
auto &AC = AssumptionCacheGetter(F);
auto &ORE = OREGetter(F); // BAM! SE is deleted here!
reallyDoTheWork(M,
F,
API,
DT,
PDT,
LI,
SE,
AC,
ORE);
}
}
}
When I use the legacy pass manager, the SE object retrieved by
SCEVGetter is deleted when the OREGetter gets the
OptimizationRemarkEmitter. Bad things ensue. Tracing through with a
debugger shows that on-the-fly passes are created and deleted a bunch of
times, including ScalarEvolution. This is because on-the-fly pass
managers are created and deleted a bunch of times, essentially each time
a *Getter is invoked.
I'm curious why the deletion happens when OREGetter is invoked. Is it
because I called OREGetter once at the top of doTheWork with the same
Function?
Is there something special about ScalarEvolution? I see that no IPO
passes use it. SCCP does the same kind of abstracting for getting pass
dependencies so I don't think the abstraction is causing the issue.
What is the proper way to run function analysis passes from a
ModulePass?
Thanks for any help!
-David
More information about the llvm-dev
mailing list