-always-inline: Inliner for always_inline Functions
Description
-always-inline pass 主要是进行把所有标记有 __always_inline 的 function 都在 IR level 上 inline 的一种 code transformation。
这样,只有当用户执行 opt -always-inline -S input.ll -o output.ll 的时候,这些有标记的 function 才会被 inline。
相比于 inline 这个function attribute 更灵活一些(因为它会在 compile 过程中被强行 inline)。
Inline 的意思就是把 callee function 中的每个 instruction 都给变成 caller function 中的 instruction,这样就解决了 function call 和 value return 的 overhead。
这里再解释一下 caller-callee 的关系,打个比方我的 main() function 调用了 vector_add() function;这里调用别人的 main() 就是 caller,另一个则是 callee。
Code Example
给定一段 C code。
__always_inline int add(int a, int b) {
return a + b;
}
int main() {
int x = 5, y = 10;
int z = add(x, y);
return 0;
}
我们先把它变成 LLVM IR。
define i32 @add(i32 %a, i32 %b) #0 {
%1 = add i32 %a, %b
ret i32 %1
}
define i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 5, i32* %1, align 4
store i32 10, i32* %2, align 4
%3 = load i32, i32* %1, align 4
%4 = load i32, i32* %2, align 4
%5 = call i32 @add(i32 %3, i32 %4)
ret i32 0
}
经过 -always-inline 之后,这个 IR 变成了。
define i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 5, i32* %1, align 4
store i32 10, i32* %2, align 4
%3 = load i32, i32* %1, align 4
%4 = load i32, i32* %2, align 4
%5 = add i32 %3, %4
ret i32 0
}