Clang 在 LLVM IR 中生成本地存储
Clang generates local store in LLVM IR
我正在通过 Clang 学习 LLVM IR,发现 C 函数如下:
int inc(int x)
{
return x+1;
}
生成此 IR(优化已关闭):
define i32 @inc(i32 %x) #0 {
entry:
%x.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
%0 = load i32, i32* %x.addr, align 4
%add = add nsw i32 %0, 1
ret i32 %add
}
我的问题是确切地知道为什么它首先分配一个本地 (x.addr) 存储,然后从中加载。
因为这是未优化的代码。 Clang(前端)并没有花费太多(几乎没有?)时间来弄清楚如何使其发出的代码最佳。它将它留给后端优化(LLVM)。局部变量在未优化模式下是"on the stack",也就是alloca
。这也意味着 x
有一个可寻址的位置,以后可能会或可能不会使用。如果没有优化,编译器不知道它是否会被使用,所以它无论如何都会保守地生成一个可寻址的位置。
int inc(int x)
{
x = x + 1;
int* px = &x;
return x;
}
现在 Clang 发出:
define i32 @inc(i32 %x) #0 {
entry:
%x.addr = alloca i32, align 4
%px = alloca i32*, align 8
store i32 %x, i32* %x.addr, align 4
%0 = load i32, i32* %x.addr, align 4
%add = add nsw i32 %0, 1
store i32 %add, i32* %x.addr, align 4
store i32* %x.addr, i32** %px, align 8
%1 = load i32, i32* %x.addr, align 4
ret i32 %1
}
看到现在用于指针的地址 %x.addr
了吗?
当然,如果您 运行 通过优化器执行此操作,您将获得:
define i32 @inc(i32 %x) #0 {
entry:
%add = add nsw i32 %x, 1
ret i32 %add
}
这可能更符合您对编译器的期望。
我正在通过 Clang 学习 LLVM IR,发现 C 函数如下:
int inc(int x)
{
return x+1;
}
生成此 IR(优化已关闭):
define i32 @inc(i32 %x) #0 {
entry:
%x.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
%0 = load i32, i32* %x.addr, align 4
%add = add nsw i32 %0, 1
ret i32 %add
}
我的问题是确切地知道为什么它首先分配一个本地 (x.addr) 存储,然后从中加载。
因为这是未优化的代码。 Clang(前端)并没有花费太多(几乎没有?)时间来弄清楚如何使其发出的代码最佳。它将它留给后端优化(LLVM)。局部变量在未优化模式下是"on the stack",也就是alloca
。这也意味着 x
有一个可寻址的位置,以后可能会或可能不会使用。如果没有优化,编译器不知道它是否会被使用,所以它无论如何都会保守地生成一个可寻址的位置。
int inc(int x)
{
x = x + 1;
int* px = &x;
return x;
}
现在 Clang 发出:
define i32 @inc(i32 %x) #0 {
entry:
%x.addr = alloca i32, align 4
%px = alloca i32*, align 8
store i32 %x, i32* %x.addr, align 4
%0 = load i32, i32* %x.addr, align 4
%add = add nsw i32 %0, 1
store i32 %add, i32* %x.addr, align 4
store i32* %x.addr, i32** %px, align 8
%1 = load i32, i32* %x.addr, align 4
ret i32 %1
}
看到现在用于指针的地址 %x.addr
了吗?
当然,如果您 运行 通过优化器执行此操作,您将获得:
define i32 @inc(i32 %x) #0 {
entry:
%add = add nsw i32 %x, 1
ret i32 %add
}
这可能更符合您对编译器的期望。