LLVM使用其他Pass的结果
之前的工作一直集中在clang中,最近有点空闲时间,又重新熟悉了一下Pass的书写过程。(参考LLVM CookBook和http://llvm.org/docs/WritingAnLLVMPass.html)
比如要实现一个基本的读取函数名的Pass,比如FuncBlockCount.cpp
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h" // ./opt load ../lib/FuncBlockCount.so -funcblockcount sample.ll
using namespace llvm;
namespace{
struct FuncBlockCount : public FunctionPass {
static char ID;
FuncBlockCount() : FunctionPass(ID) { }
bool runOnFunction(Function& F) override {
errs() << "Function" << F.getName() << '\n';
return false;
}
};
char FuncBlockCount::ID = ;
static RegisterPass<FuncBlockCount> X("funcblockcount", "Function Block Count", false, false);
}
大概过程就是,实现一个类(在C++中,struct和class只是有一些访问控制的不同,具体可以百度),这个类需要继承至各种Pass,一般都是从FunctionPass作为入口,如果你对全局信息有需求的话,建议可以考虑ASTModule。
然后需要一个ID,其实这个ID不是特别关键,然后是注册Pass,有4个参数,第一个是执行的时候调用的命令,第二个是介绍。
看起来非常简单,就是三步:
1.写一个带有runOnxxx的类,这个类需要继承至Pass
2. 给一个初始ID
3.注册Pass
花几分钟读一下代码,其实发现最简单的Pass其实就是这么简单
写好了代码,下面介绍如何进行编译和链接,由于现在llvm主要依靠cmake来生成Makefile文件,所以要想这个Pass能运行,需要在合适的地方写CMakeList.txt文件。
这里,为了简化,介绍最简单的方式。在your_src_dir/lib/Transforms/下,新建一个文件夹,我这里新建的是FuncBlockCount,如果一切都正常的话,下边一般会有Scalar,Vectorize,Hello等这几个文件夹
在Transforms目录下的CMakeLists.txt中添加
add_subdirectory(FuncBlockCount)
切换到新建的FuncBlockCount下,将刚才FuncBlockCount.cpp复制到下边,然后新建CMakeLists.txt,内容如下:
add_llvm_loadable_module( FuncBlockCount
FuncBlockCount.cpp DEPENDS
intrinsics_gen
)
然后重新cmake,make就可以生成FuncBlockCount.so文件了
写一个简单的sample.c测试一下
int foo(int n, int m)
{
int sum = ;
sum = n + m;
return sum;
}
使用-emit-llvm生成ll文件
./clang -O0 -S -emit-llvm sample.c -o sample.ll
再用opt加载就可以了
./opt -load ../lib/FuncBlockCount.so -funcblockcount sample.ll
可以看到,成功的输出了
Functionfoo
这里,我们已经成功地完成了一个Pass,下面我们希望能做一点有挑战的事情,在我们的Pass中使用其他Pass,这里我们使用LoopInfoWrapperPass,这是一个分析循环信息的Pass
在FuncBlockCount.cpp中插入
namespace {
// Hello2 - The second implementation with getAnalysisUsage implemented.
struct GetLoopInfo2 : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
GetLoopInfo2() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
errs() <<"Function "<< F.getName() << '\n';
for(Loop *L : *LI)
{
countBlocksInLoop(L, );
}
return false;
}
// We don't modify the program, so we preserve all analyses.
void countBlocksInLoop(Loop* L, unsigned nest) {
unsigned num_Blocks = ;
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+);
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<LoopInfoWrapperPass>();
//AU.setPreservesAll();
}
};
}
char GetLoopInfo2::ID = ;
static RegisterPass<GetLoopInfo2> Y("getLoopInfo2", "Get LoopInfo2");
这里其他部分变化不大,对于结构方面,添加了一个新的函数getAnalysisUsage,这个函数重载了原来Pass中的对应函数,告诉Pass管理器,我们的Pass依赖于LoopInfoWrapperPass
重新编译生成后,我们新写一个测试例子,刚才的例子太简单了,都没有循环结构,完全无法体现出这个Pass的作用
sample1.cpp
// ./opt load ../lib/FuncBlockCount.so -getLoopInfo2 sample1.ll
int main(int argc, char** argv)
{
int i,j,k , t= ;
for(i=; i< ;i++)
{
for(j=;j<;j++)
{
for(k=;k<;k++)
{
t++;
}
}
for(j=;j<;++j)
{
t++;
}
}
for(i=;i<;i++)
{
for(j=;j<;j++)
{
t++;
}
}
return t;
}
生成sample1.ll文件后,使用如下命令
./opt -load ../lib/FuncBlockCount.so -getLoopInfo2 sample1.ll -disable-output -debug-pass=Structure
成功可以看到输出:

如果不使用调试pass的方式,就是去掉-debug-pass选项,只有

但是,如果你忘记了添加对LoopInfoWrapperPass的依赖,那么就会呈现类似的报错信息

LLVM使用其他Pass的结果的更多相关文章
- 全图化引擎(AI·OS)中的编译技术
全图化引擎又称算子执行引擎,它的介绍可以参考从HA3到AI OS -- 全图化引擎破茧之路.本文从算子化的视角介绍了编译技术在全图化引擎中的运用.主要内容有: 1. 通过脚本语言扩展通用算子上的用户订 ...
- iOS 覆盖率检测原理与增量代码测试覆盖率工具实现
背景 对苹果开发者而言,由于平台审核周期较长,客户端代码导致的线上问题影响时间往往比较久.如果在开发.测试阶段能够提前暴露问题,就有助于避免线上事故的发生.代码覆盖率检测正是帮助开发.测试同学提前发现 ...
- 编译器优化:何为SLP矢量化
摘要:SLP矢量化的目标是将相似的独立指令组合成向量指令,内存访问.算术运算.比较运算.PHI节点都可以使用这种技术进行矢量化. 本文分享自华为云社区<编译器优化那些事儿(1):SLP矢量化介绍 ...
- 开发和调试第一个 LLVM Pass
1. 下载和编译 LLVM LLVM 下载地址 http://releases.llvm.org/download.html,目前最新版是 6.0.0,下载完成之后,执行 tar 解压 llvm 包: ...
- 从OLLVM4.0.0升级到LLVM8.0.1,并且给LLVM增加Pass 插件系统
版本太低了,用得我这个揪心. 上周日决定把手头的ollvm从4.0.0升级到LLVM8.0.1. 里面的Pass的话,决定移植到8.0.1里面. 我习惯从代码上来动手 1:下载LLVM https: ...
- llvm pass
https://polly.llvm.org/docs/Architecture.html#polly-in-the-llvm-pass-pipeline
- llvm -O 经历过那些pass
https://stackoverflow.com/questions/15548023/clang-optimization-levels
- LLVM example for main
#include "llvm/IR/CallSite.h" #include "llvm/IR/Instruction.h" #include "ll ...
- LLVM language 参考手册(译)(1)
LLVM Language Reference Manual 摘要 这个文档是一个LLVM汇编语言的参考手册.LLVM是一个基于Static Single Assignment(SSA - 静态单赋值 ...
随机推荐
- numpy中flatten学习笔记
ndarray.flatten() 用法 用于返回一个折叠成一维的数组.该函数只能适用于numpy对象,即array或者mat,普通的list列表是不行的. 例子 # coding=utf-8 fro ...
- 实用的在线预览数据字典的工具(php编写)
前言 无论是刚接手新项目,或者是维护老项目,有一个方便的数据字典可用是最棒哒! 本文是我为了方便使用数据字典而写的代码. 代码无版权,随便使用. 拷贝代码后,只需修改数据库名,主机,用户名,密码,开箱 ...
- C++ STL 逆转旋转 reverse reverse_copy rotate
#include <iostream>#include <algorithm>#include <vector>#include <iterator> ...
- 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_22-CMS前端页面查询开发-Api调用-跨域解决
点击页面查询按钮 ,报错.跨域问题. 前端端口是11000 请求后端的服务地址端口是31001 出现跨域 开始解决跨域 把前面带端口的地址 用变量代替 只有带/api/cms开头的就转发的服务端310 ...
- [Scikit-learn] 1.5 Generalized Linear Models - SGD for Regression
梯度下降 一.亲手实现“梯度下降” 以下内容其实就是<手动实现简单的梯度下降>. 神经网络的实践笔记,主要包括: Logistic分类函数 反向传播相关内容 Link: http://pe ...
- JS 事件介绍
1.设置js对象属性为事件处理程序 事件处理程序属性的名字由“on”后面跟着事件名组成.这些属性名 都必须小写 事件处理程序的缺点:设计都是围绕着假设每个事件目标对于每种事件类型将最多只有一个处理程序 ...
- [PyTorch] Facebook Research - Mask R-CNN Benchmark 的安装与测试
Github项目链接:https://github.com/facebookresearch/maskrcnn-benchmark maskrcnn_benchmark 安装步骤: 安装Anacond ...
- javascript语法 1.运算符 2. 流程控制 3. 函数 4. 四种变量 5. 数据类型的运用 6. js页面交互
1.运算符 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <tit ...
- Beta冲刺博客
这个作业属于哪个课程 当然是属于程序分析与设计呀 这个作业要求在哪里 在这儿 团队名称 六扇门编程小组(团队博客) 这个作业的目标 完成为期两周的β版本冲刺 1.团队信息 姓名 学号 曹欢(组长) 2 ...
- ssh速度慢
原因:DNS解析默认开了 解决方法: vi /etc/ssh/sshd_config, 将#UseDNS yes 改为 : UseDNS no 然后重启ssh服务即可. PS: 其实不好,因为毕竟 ...