LLVM IR 中的“select”和“phi”有什么区别?
What is the difference between `select` and `phi` in LLVM IR?
比如我有一段C代码:
void foo(int x) {
int y;
if (x > 0) {
y = 1;
} else {
y = 2;
}
// do something with y
}
为了简化 LLVM IR 级别的代码(其中 y
可以放在寄存器而不是堆栈中),我可以使用 select
:
define void @foo(i32 %x) {
%result = icmp sgt i32 %x, 0
%y = select i1 %result, i32 1, i32 2
; do something with %y
}
但是,如果我使用phi
,代码会变得更长:
define void @foo(i32 %x) {
%result = icmp sgt i32 %x, 0
br i1 %result, label %btrue, label %bfalse
btrue:
br label %end
bfalse:
br label %end
end:
%y = phi i32 [1, %btrue], [2, %bfalse]
; do something with %y
ret void
}
据我所知,phi
相对于select
的唯一优势是phi
支持2个以上的分支,而select
只支持2个分支。除了这种情况,有没有其他情况phi
比select
好?
select
的操作数只有Value
,而phi
的操作数是一对Value
和BasicBlock
。
另一个区别是phi
可以翻转函数的控制流,而select
只允许根据布尔值在两个值之间进行选择。粗略地说,select
对应的是?:
三元运算符,phi
对应的是Cswitch
语句,有很多情况。
比如我有一段C代码:
void foo(int x) {
int y;
if (x > 0) {
y = 1;
} else {
y = 2;
}
// do something with y
}
为了简化 LLVM IR 级别的代码(其中 y
可以放在寄存器而不是堆栈中),我可以使用 select
:
define void @foo(i32 %x) {
%result = icmp sgt i32 %x, 0
%y = select i1 %result, i32 1, i32 2
; do something with %y
}
但是,如果我使用phi
,代码会变得更长:
define void @foo(i32 %x) {
%result = icmp sgt i32 %x, 0
br i1 %result, label %btrue, label %bfalse
btrue:
br label %end
bfalse:
br label %end
end:
%y = phi i32 [1, %btrue], [2, %bfalse]
; do something with %y
ret void
}
据我所知,phi
相对于select
的唯一优势是phi
支持2个以上的分支,而select
只支持2个分支。除了这种情况,有没有其他情况phi
比select
好?
select
的操作数只有Value
,而phi
的操作数是一对Value
和BasicBlock
。
另一个区别是phi
可以翻转函数的控制流,而select
只允许根据布尔值在两个值之间进行选择。粗略地说,select
对应的是?:
三元运算符,phi
对应的是Cswitch
语句,有很多情况。