LLVM在std :: vector中存储Loop *

时间:2014-10-24 10:40:14

标签: c++ loops llvm llvm-c++-api

我偶然发现了一些非常特殊的东西 - 我正在写一个LLVM模块Pass。我迭代模块的所有函数,然后迭代每个非声明函数的所有循环,并将指针存储到std::vector中的循环。这是来源:

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

现在,如果我运行这个,我得到一个运行时错误 - 它无法打印循环,不知怎的,我正在做空指针取消引用或某事。有什么想法吗?

4 个答案:

答案 0 :(得分:1)

您必须确保LoopInfo通行证在通行证之前实际运行。这是一个完整的示例 - 来自opt的stanalone:

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

此外,在创建传球时,请执行以下操作:

  PassManager PM;
  PM.add(new LoopInfo());
  PM.add(new AnalyzeLoops());
  PM.run(*Mod);

我怀疑要让opt在你通过之前实际运行LoopInfo,你也应该通过-loops

另外,请注意我定义getAnalysisUsage - 如果LoopInfo在此次传递之前未运行,这将使LLVM抱怨,从而使问题更加明显。


请注意,LoopInfo具体为FunctionPass,作为分析,必须使用其他FunctionPassLoopInfo数据结构在不同函数之间并不存在,并且由于它拥有其数据(那些Loop*对象),它们也将被销毁。

如果你真的需要ModulePass,你可以做的一件事就是手动调用LoopInfo而不是分析。当您迭代模块中的函数时,为每个函数创建一个新的LoopInfo对象并使用其runOnFunction方法。虽然在这种情况下,如果您想使用后者,您必须确保拥有给定LoopInfo的{​​{1}}幸存。

答案 1 :(得分:1)

首先,LoopInfo应该在for循环之前运行一次。 其次,LoopInfo :: iterator只包含Function的顶级循环。为了访问所有循环,您还需要迭代每个循环的子循环。它既可以作为递归函数实现,也可以通过WorkList实现,如此`

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

答案 2 :(得分:1)

没有一个答案真的有帮助,但我自己设法解决了这个问题。基本上,每个llvm pass都可以定义一个releaseMemory()方法,阅读更多here。 LoopInfo类实现了该方法,因此每次调用getAnalysis时,分析信息都会丢失。我只是删除了Loopinfo.h中的releaseMemory()方法,并且不再释放内存。请注意,这触发了代码库的一个重大变化,甚至必须重建,所以这样做通常可能是一个坏主意,这肯定不会被轻易接受为llvm的变化(我推测,不确定)。

答案 3 :(得分:0)

我认为解决此问题的最佳方法是显式创建LoopInfo对象并保存它们。这是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";
  }
}