在LLVM IR中为文本值分配局部变量

时间:2014-07-07 07:25:21

标签: assembly llvm llvm-clang llvm-ir

我一直在搞乱LLVM IR的代码生成,而且我不太了解这一点,这就是必须分配局部变量的区别,以及如何将文字值加载到局部变量中。如果我将以下简单的C代码编译为LLVM IR,

//test.c
int main() {
    int x = 3;
    int y = x + 4;
    return y;
}

我得到了这个输出:

; ModuleID = 'test.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.10.0"

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
    %1 = alloca i32, align 4
    %x = alloca i32, align 4
    %y = alloca i32, align 4
    store i32 0, i32* %1
    store i32 3, i32* %x, align 4
    %2 = load i32* %x, align 4
    %3 = add nsw i32 %2, 4
    store i32 %3, i32* %y, align 4
    %4 = load i32* %y, align 4
    ret i32 %4
}

attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.ident = !{!0}

!0 = metadata !{metadata !"Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)"}

我可以减少到

target triple = "x86_64-apple-macosx10.10.0"

define i32 @main() {
    %t1 = alloca i32
    store i32 3, i32* %t1
    %x = add nsw i32 0, 3

    %y = add nsw i32 %x, 4
    ret i32 %y
}

所以我想我的问题是,为什么这样一个将文字数加载到变量中的迂回方法?有更好/更直接的方式吗?另外,为什么%t1需要alloca - ed,但%x%y不是?

1 个答案:

答案 0 :(得分:4)

Clang负责生成第一个代码段。 Clang选择最简单的方法为这些指令生成IR - 即为每个指令分配内存,然后存储并加载到此内存。这创建了可以模拟C变量语义的IR,可以在整个生命周期内重新分配不同的值 - 在LLVM IR中没有这样的东西(没有变量 - read more about SSA)。

Clang所做的只是编译的第一步。然后,该IR将通过许多变换(称为“通过”)。一个人将负责getting rid of the memory use,正如您在第二个片段中所示 - 这将允许稍后使用寄存器而不是堆栈来获取这些值。另一个传递将get rid of the unused value %t1,另一个将identify that constants are being used here and will replace the entire function body with return i32 7 ...等等。

总而言之,它不是一种“迂回的方式”,它只是Clang生成IR的最简单方法,并且使IR更好是后来LLVM传递的责任。