如何在新的Pass中调用其他Pass(订正LLVM COOKBOOK中一些小问题)

1 篇文章 0 订阅
1 篇文章 0 订阅

一个Pass可能会需要其他Pass以得到分析数据、启发或类似信息来指导自己的行为。例如,一个Pass可能会需要一些对内存依赖性的分
析,或者需要修改过的IR。我们在前一节编写的Pass仅仅是输出了函数名,本节我们会对其增强,使它能够对循环中的基本块进行计数,以介
绍如何使用其他Pass的结果。

在这里我们实现一个基本快计数的pass---------FuncBlockCount

编写一个pass,首先需要编写CmakeList.txt

if( NOT LLVM_REQUIRES_RTTI )
  if( NOT LLVM_REQUIRES_EH )
    set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/FuncBlockCount.exports)
  endif()
endif()

if(WIN32 OR CYGWIN)
  set(LLVM_LINK_COMPONENTS Core Support)
endif()

add_llvm_loadable_module( FuncBlockCount
  FuncBlockCount.cpp

  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )

其次,在FuncBlockCount.cpp中写入

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"

#include "llvm/Analysis/LoopInfo.h"
using namespace llvm;
namespace {
  // Hello2 - The second implementation with getAnalysisUsage implemented.
  struct FuncBlockCount : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    FuncBlockCount() : FunctionPass(ID) {}

    bool runOnFunction(Function &F) override {
      LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
      errs() <<"Function "<< F.getName() << '\n';
      for(Loop *L : *LI)
      {
          countBlocksInLoop(L, 0);
      }
      return false;
    }

    // We don't modify the program, so we preserve all analyses.
    void countBlocksInLoop(Loop* L, unsigned nest) {
      unsigned num_Blocks = 0;
      Loop::block_iterator bb;
      for(bb = L->block_begin(); bb != L->block_end(); ++bb)
      {
          num_Blocks ++;
      }
      errs() << "Loop Level "<< nest << " has "<< num_Blocks<< " Blocks\n";
      std::vector<Loop*> subLoops =L->getSubLoops();
      Loop::iterator j, f;
      for(j = subLoops.begin(), f= subLoops.end();j!=f;++j)
          countBlocksInLoop(*j, nest+1);
    }
    
    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.addRequired<LoopInfoWrapperPass>();
      //非常重要的代码段
    }
  };
  
}
char FuncBlockCount::ID = 0;
static RegisterPass<FuncBlockCount> X("funcblockcount", "func block count",false,false);

for(Loop *L : *LI)//该循环指针问题需要订正
      {
          countBlocksInLoop(L, 0);
      }

以上代码会遍历循环,对其中的基本块进行计数。但它只对最外层循环中的基本块计数。如果想要得到内层循环的信息,还需要递归地
调用getSubLoops函数进行计数。把逻辑放在单独的函数中,然后递归。

其中getAnalysisUsage函数重载了原来Pass中的对应函数,告诉Pass管理器,我们的Pass依赖于LoopInfoWrapperPass

void getAnalysisUsage(AnalysisUsage &AU) const override {
   AU.addRequired<LoopInfoWrapperPass>();
}

基本的pass结构还需要一个FuncBlockCount.exports文件,该文件为空即可。

接下来再在父级目录的CMakeList.txt中add_subdirectory(FuncBlockCount)即可。

一个基本的pass编写完毕。

 

然后再测试pass,编写一个sample.c文件如下

int main(int argc, char** argv)
{
    int i,j,k , t= 0;
    for(i=0; i< 10;i++)
    {
        for(j=0;j<10;j++)
        {
            for(k=0;k<10;k++)
            {
                t++;
            }    
        }
        for(j=0;j<10;++j)
        {
            t++;
        }
    }
    for(i=0;i<20;i++)
    {
        for(j=0;j<20;j++)
        {
            t++;
        }
    }
    return t;
}

然后通过sample.c文件所在目录运行,生成sample.ll文件

clang -O0 -S -emit-llvm sample.c -o sample.ll

然后在llvm的build目录下 make -j4    即可成功编译

最后,找到在build/lib下的FuncBlockCount.so文件进行操作

opt -load ../../llvm/build/lib/FuncBlockCount.so -funcblockcount sample.ll

成功如下:

如果没有添加getAnalysisUsage函数对LoopInfoWrapperPass的依赖,就会报错如下

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值