i转换以下llvm-ir
; Function Attrs: noinline norecurse nounwind uwtable
define i32 @main() #0{
entry:
%sub = sub nsw i32 5, 3
%cmp = icmp slt i32 %sub, 3
br i1 %cmp, label %if.then, label %if.else
if.then: ; preds = %entry
%mul = mul nsw i32 %sub, 2
br label %if.end
if.else: ; preds = %entry
%sub1 = sub nsw i32 %sub, 3
br label %if.end
if.end: ; preds = %if.else,
%if.then
%y.0 = phi i32 [ %mul, %if.then ], [ %sub1, %if.else ]
%sub2 = sub nsw i32 %sub, %y.0
%add = add nsw i32 %sub, %y.0
ret i32 0
}
到x86_64-unknown-linux-gnu
的汇编代码使用llc sample.ll
生成的装配代码:
.text
.file "phi.cpp"
.globl main # -- Begin function main
.p2align 4, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0: # %entry
pushq %rbp
.Lcfi0:
.cfi_def_cfa_offset 16
.Lcfi1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Lcfi2:
.cfi_def_cfa_register %rbp
xorl %eax, %eax
testb %al, %al
xorl %eax, %eax
popq %rbp
retq
.Lfunc_end0:
.size main, .Lfunc_end0-main
.cfi_endproc
# -- End function
上述代码中的寄存器:%rbp
是基本指针,指向当前堆栈框架的底部,而%rsp
是堆栈指针,它指向当前堆栈框架的顶部,并且操作数存储在%eax
中和%al
用于算术操作,但在%eax
和%al
寄存器中的值是加载的指令中我也想知道
- LLC如何处理phi节点上的phi节点
lli
默认为 -O2
,而您的代码则以常量的表达式sub nsw i32 5, 3
开始。因此,您的功能基本上是什么都没有的,而LLVM应该保留的唯一一件事就是无效eax。
如果运行lli -O0 your.ll
,您将获得很多详细的代码,这些代码在堆栈上执行溢出并注册负载。
顺便说一句,有一对称为mem2reg
和reg2mem
的通行证,可以从SSA表单来回代码。具体而言,这些通过将phi
节点转换为分支,并在IR中引入显式商店和负载。