我正在尝试编写一个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;似乎在函数结束时起作用。所以我遇到两个问题:
为什么要&#34; doInitialization&#34;多次工作?
如果我想得到一个程序中的循环总数(一个程序可能有很多功能,我确实需要&#34; doFinalization&#34;只能为一个程序工作一次),我该怎么办
感谢所有相关答案,
答案 0 :(得分:1)
为什么多次调用doInitialization
?
计算程序中的所有循环,我会写一个ModulePass
并覆盖其runOnModule()
。模块M
您可以访问所有函数(我认为begin
和end
函数应返回适当的迭代器)。
然后我可以使用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()
并通过调用LoopInfo
向AU.addRequired<LoopInfo>()
添加依赖项。
答案 1 :(得分:0)
因为循环传递没有为整个编译初始化一次,所以每次分析循环时都会初始化它。
我将调试语句添加到现有的循环传递中,该传递会打印一些独特的东西,然后在grep -c
-debug-only=<pass_you_modified>