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?

+3


source to share


4 answers


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.

+1


source


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);
    }
  }
}
` 

      

+1


source


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).

+1


source


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";
  }
}

      

0


source







All Articles