LLVM saving Loop * to std :: vector
I stumbled upon something very peculiar - I'm writing an LLVM Pass module. I iterate over all the functions of a module and then all loops of each function without declaration, and I store the loop pointers in std::vector
. Here's the source:
virtual bool runOnModule(Module& Mod){
std::vector<Loop*> loops;
// first gather all loop info
for(Module::iterator f = Mod.begin(), fend = Mod.end(); f != fend; ++f){
if (!(*f).isDeclaration()){
LoopInfo& LI = getAnalysis<LoopInfo>(*f);
for(LoopInfo::iterator l = LI.begin(), lend = LI.end(); l != lend; ++l){
loops.push_back(*l);
}
}
}
for (auto& l: loops) errs () << *l << " ";
}
Now if I run this I get a runtime error - it cannot print loops, anyway I do a null pointer or sth pivot. Any ideas?
source to share
You must make sure that the pass is LoopInfo
actually done before your pass. Here's a complete example - stanalon from opt
:
class AnalyzeLoops : public FunctionPass {
public:
AnalyzeLoops()
: FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LoopInfo>();
}
virtual bool runOnFunction(Function &F) {
LoopInfo &LI = getAnalysis<LoopInfo>();
for (LoopInfo::iterator L = LI.begin(), LE = LI.end(); L != LE; ++L) {
(*L)->dump();
}
return false;
}
static char ID;
};
Additionally, when creating passes, do:
PassManager PM;
PM.add(new LoopInfo());
PM.add(new AnalyzeLoops());
PM.run(*Mod);
I suspect that before opt
actually doing the run LoopInfo
in front of your pass, you must pass as well -loops
.
Also note that I define getAnalysisUsage
- this will cause LLVM to complain if LoopInfo
not executed before this pass, making the problem more obvious.
Note that LoopInfo
- this is in particular FunctionPass
, and as an analysis it should be used from another FunctionPass
. The data structure LoopInfo
doesn't really survive between different functions, and since it owns its data (those Loop*
objects) they will be destroyed as well.
One thing you could do, if you really need to ModulePass
, is to just call it LoopInfo
manually, not as an analysis. When you repeat functions in a module, create a new object for each function LoopInfo
and use its method runOnFunction
. Even so, though, you have to make sure that the LoopInfo
one that owns the given Loop*
is preserved if you want to use the latter.
source to share
First of all, LoopInfo should only run once before the for loop. Second, LoopInfo :: iterator only includes the top levels of the function. in order to visit all the cycles, you also need to iterate over the subloops of each cycle. it can be implemented either as a recursive function or with a WorkList like this`
virtual bool runOnFunction(Function &F) {
LoopInfo *loopinfo;
loopinfo = &getAnalysis<LoopInfo>();
std::vector<Loop*> allLoops;
for (LoopInfo::iterator Li = loopinfo->begin(), Le = loopinfo->end();
Li != Le; Li++) {
Loop *L = *Li;
allLoops.push_back(L);
dfsOnLoops(L, loopinfo, allLoops);
}
}
void dfsOnLoops(Loop *L, LoopInfo *loopinfo, std::vector<Loop*> LoopS) {
std::vector<Loop *> subloops = L->getSubLoops();
if (subloops.size()) {
// recursive on subloops
for (std::vector<Loop *>::iterator Li = subloops.begin();Li != subloops.end(); Li++){
LoopS.push_back(*Li);
dfsOnLoops(*Li, loopinfo, LoopS);
}
}
}
`
source to share
None of the answers helped, but I managed to fix the problem myself. Basically, each llvm pass can define a releaseMemory () method, read here . The LoopInfo class has implemented this method and therefore the analysis information will be lost every time we go out of scope from the getAnalysis call. I just removed the releaseMemory () method in Loopinfo.h and the memory was no longer released. Note that this caused big changes in the codebase and even opt had to be rebuilt, so in general this is probably a bad idea and it definitely won't be easily perceived as a llvm change (I'm not sure, I'm guessing).
source to share
I think the best way to solve this is to explicitly create LoopInfo objects and store them. Here is the code for LLVM 3.5
using LoopInfoType=llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>;
std::vector<llvm::Loop*> loopVec;
std::vector<LoopInfoType*> loopInfoVec;
for(llvm::Module::iterator F = M.begin(); F!= M.end(); F++){
//skip declrations
if(F->isDeclaration()){
continue;
}
//TODO that scope problem
llvm::DominatorTree DT = llvm::DominatorTree();
DT.recalculate(*F);
LoopInfoType *loopInfo = new LoopInfoType();
loopInfo->releaseMemory();
loopInfo->Analyze(DT);
loopInfoVec.push_back(loopInfo);
for(llvm::LoopInfo::iterator lit = loopInfo->begin(); lit != loopInfo->end(); lit++){
Loop * L = * lit;
loopVec.push_back(L);
//L->dump();
}
}//for all functions
cin.get();
for(auto loop : loopVec){
std::cout << "loop\n";
loop->dump();
for(llvm::Loop::block_iterator bit = loop->block_begin(); bit != loop->block_end(); bit++){
llvm::BasicBlock * B = * bit;
B->dump();
std::cout << "\n\n";
}
}
source to share