尝试使用llvm LoopPass查找程序

时间:2015-10-26 22:40:23

标签: llvm

我正在尝试编写一个llvm pass程序来计算程序中的循环次数。然后我找到了LoopPass,其解释如下:

http://llvm.org/docs/WritingAnLLVMPass.html#the-looppass-class

提到了三个函数:doInitialization,runOnLoop,doFinalization。

我最初认为" doInitialization"在程序开始时运行一次," runOnLoop"每次循环结束时运行," doFinalization"在程序结束时运行。我想将变量定义为计数器,设置为" 0"在" doInitialization"中,计算++中" runOnLoop",并在" doFinalization"中输出结果。

这是我的代码(部分):

virtual bool doInitialization(Loop * L, LPPassManager &LPM)
{
    errs() << (*(L->block_begin()))->getParent()->getName() << '\n';
    count = 0;
    length = 0;

    return false;
}

virtual bool runOnLoop(Loop * L, LPPassManager &LPM){

  count++;
  for(Loop::block_iterator b = L->block_begin(), e = L->block_end(); b != e; b++)
  {
    length++;
  }

  return false;
}

virtual bool doFinalization()
{
    errs() << "# of loops:              " << count << '\n';
    errs() << "average depth of loop:       " << (float)(length)/count << '\n';

    return false;
}

但是从结果来看,&#34; doInitialization&#34;似乎工作的次数等于一个函数中的循环次数,&#34; runOnLoop&#34;按预期工作,&#34; doFinalization&#34;似乎在函数结束时起作用。所以我遇到两个问题:

  1. 为什么要&#34; doInitialization&#34;多次工作?

  2. 如果我想得到一个程序中的循环总数(一个程序可能有很多功能,我确实需要&#34; doFinalization&#34;只能为一个程序工作一次),我该怎么办

  3. 感谢所有相关答案,

2 个答案:

答案 0 :(得分:1)

为什么多次调用doInitialization

计算程序中的所有循环,我会写一个ModulePass并覆盖其runOnModule()。模块M您可以访问所有函数(我认为beginend函数应返回适当的迭代器)

然后我可以使用getAnalysis()来获取指定函数的LoopInfo对象。该对象提供迭代器迭代所有顶级循环。如果这样的循环包含嵌套循环,则所有嵌套循环都是&#34;第二级&#34;可以使用getSubLoops检索。因此,对于嵌套循环,您必须递归使用getSubLoops,直到不再存在子循环。然后我可以为每个循环对象增加一些计数器。所以它看起来像这样(我知道代码没有编译):

int loopcounter;
void handleLoop(Loop *L) {
  ++loopcounter;
  for (Loop *SL : L->getSubLoops()) {
    handleLoop(SL);
  }
}
virtual bool runOnModule(Module&M) {
  loopcounter = 0;
  for (auto &IT = M.begin, END = M.end(); IT != END; ++IT) {
    LoopInfo &LI = getAnalysis<LoopInfo>(*IT);
    for (LoopInfo::iterator LIT = LI.begin(), LEND = LI.end(); LIT != LEND; ++LIT) {
      handleLoop(*LIT);
    }
  }
  DEBUG(errs() << "Found " << loopcounter << " loops.\n");
}

要使getAnalysis调用正常工作,您必须覆盖getAnalysisUsage()并通过调用LoopInfoAU.addRequired<LoopInfo>()添加依赖项。

答案 1 :(得分:0)

  1. 因为循环传递没有为整个编译初始化一次,所以每次分析循环时都会初始化它。

  2. 我将调试语句添加到现有的循环传递中,该传递会打印一些独特的东西,然后在grep -c

    的汇总输出上使用-debug-only=<pass_you_modified>