llvm被设计成一系列库的集合。什么意思?就是每个模块都可以拿出来单独使用。
本文用llvm优化器opt命令行工具来展示它的模块化用法。
编写文件 testfile.ll
define i32 @test1(i32 %A) {
%B = add i32 %A, 0
ret i32 %B
}
define internal i32 @test(i32 %X, i32 %dead) {
ret i32 %X
}
define i32 @caller() {
%A = call i32 @test(i32 123, i32 456)
ret i32 %A
}
在任意目录执行如下命令
opt -S -instcombine testfile.ll -o output1.ll
输出文件 output1.ll
内容如下
; ModuleID = 'testfile.ll'
source_filename = "testfile.ll"
define i32 @test1(i32 %A) {
ret i32 %A
}
define internal i32 @test(i32 %X, i32 %dead) {
ret i32 %X
}
define i32 @caller() {
%A = call i32 @test(i32 123, i32 456)
ret i32 %A
}
可以看到函数 test1 中的指令被合并了,这就是instcombine
的作用。
再次执行命令:
opt -S -deadargelim testfile.ll -o output2.ll
输出output2.ll
如下:
; ModuleID = 'testfile.ll'
source_filename = "testfile.ll"
define i32 @test1(i32 %A) {
%B = add i32 %A, 0
ret i32 %B
}
define internal i32 @test(i32 %X) {
ret i32 %X
}
define i32 @caller() {
%A = call i32 @test(i32 123)
ret i32 %A
}
这一次,指令没有合并,但test函数中没有用到的参数被删除了,就是 deadargelim
的作用。
llvm优化器的各pass相互不知道依赖关系,这个关系主要靠 PassManager
来管理。
除了优化器,还有代码生产器中的各模块也可以独立使用,包括
- instruction selection
- register allocation
- scheduling
- code layout optimization
- assembly emission