CLang++ 在 LLVM_IR 中生成虚假变量
CLang++ generating spurious vars in LLVM_IR
请考虑以下方案:
int main() {
int test = 17;
return test;
}
编译为 LLVM_IR:clang++ -S -emit-llvm test.cpp
查看IR,函数main定义如下:
; Function Attrs: noinline norecurse nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 17, i32* %2, align 4
%3 = load i32, i32* %2, align 4
ret i32 %3
}
我们可以看到%2
是我们test
变量的分配,加载17
进去,%3
使用那个变量作为函数的return 值(与我们编写的代码保持一致)。然而,我们看到 %1
定义了另一个 int
大小的变量,并将其初始化为 0,尽管从未使用过它。这个额外的变量在 C++ 源代码中是看不到的。
我应该注意到,当我使用 clang
而不是 clang++
编译时,我看到生成了相同的内容。
这个额外的变量是什么?
我假设您使用的是旧版本的 clang
。在新版本中(我指的是 v7.0 及更高版本),默认打印值名称。但要明确打印,您可能 -fno-discard-value-names
。使用此选项,您将获得以下 IR:
define dso_local i32 @main() #0 {
entry:
%retval = alloca i32, align 4
%test = alloca i32, align 4
store i32 0, i32* %retval, align 4
store i32 17, i32* %test, align 4
%0 = load i32, i32* %test, align 4
ret i32 %0
}
现在很清楚 store 0
的来源了。在未优化的代码中,编译器将 retval
初始化为 0
。
请考虑以下方案:
int main() {
int test = 17;
return test;
}
编译为 LLVM_IR:clang++ -S -emit-llvm test.cpp
查看IR,函数main定义如下:
; Function Attrs: noinline norecurse nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 17, i32* %2, align 4
%3 = load i32, i32* %2, align 4
ret i32 %3
}
我们可以看到%2
是我们test
变量的分配,加载17
进去,%3
使用那个变量作为函数的return 值(与我们编写的代码保持一致)。然而,我们看到 %1
定义了另一个 int
大小的变量,并将其初始化为 0,尽管从未使用过它。这个额外的变量在 C++ 源代码中是看不到的。
我应该注意到,当我使用 clang
而不是 clang++
编译时,我看到生成了相同的内容。
这个额外的变量是什么?
我假设您使用的是旧版本的 clang
。在新版本中(我指的是 v7.0 及更高版本),默认打印值名称。但要明确打印,您可能 -fno-discard-value-names
。使用此选项,您将获得以下 IR:
define dso_local i32 @main() #0 {
entry:
%retval = alloca i32, align 4
%test = alloca i32, align 4
store i32 0, i32* %retval, align 4
store i32 17, i32* %test, align 4
%0 = load i32, i32* %test, align 4
ret i32 %0
}
现在很清楚 store 0
的来源了。在未优化的代码中,编译器将 retval
初始化为 0
。