3

我偶然发现了一些非常奇怪的东西——我正在写一个 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

4 回答 4

1

您必须确保LoopInfo通行证在您的通行证之前实际运行。这是一个完整的例子 - stanalone 来自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;
};

此外,在创建通道时,请执行以下操作:

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

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

另外,请注意我定义的- 如果在此通过之前没有运行,这getAnalysisUsage将使 LLVM 抱怨,使问题更加明显。LoopInfo


请注意,LoopInfo它特别是 a FunctionPass,并且作为分析,它必须从另一个FunctionPass. LoopInfo数据结构并不能真正在不同的函数之间存在,并且由于它拥有它的数据(那些对象Loop*),它们也会被销毁。

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

于 2014-10-24T16:20:05.927 回答
1

首先 LoopInfo 应该在 for 循环之前运行一次。其次 LoopInfo::iterator 只包含函数的顶层循环。为了访问所有循环,您还需要遍历每个循环的子循环。它可以实现为递归函数或工作列表,像这样`

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);
    }
  }
}
` 
于 2015-04-23T13:59:41.720 回答
1

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

于 2016-10-30T16:09:52.077 回答
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";
  }
}
于 2018-01-30T20:53:17.197 回答