PHI指令的确切作用以及如何在LLVM中使用它 [英] What exactly PHI instruction does and how to use it in LLVM
问题描述
LLVM具有 phi 指令,其中的解释很奇怪:
LLVM has phi instruction with quite weird explanation:
'phi'指令用于在表示该函数的SSA图中实现φ节点.
通常,它用于实现分支.如果我理解正确,则需要使依赖关系分析成为可能,并且在某些情况下可以帮助避免不必要的加载.但是,仍然很难理解它的确切作用.
Typically it is used to implement branching. If I understood correctly, it is needed to make dependency analysis possible and in some cases it could help to avoid unnecessary loading. However it's still hard to understand what it does exactly.
万花筒示例对此进行了解释对于if
情况来说相当不错.但是,还不清楚如何实现&&
和||
之类的逻辑操作.如果我在在线llvm 编译器中输入以下内容:
Kaleidoscope example explains it fairly nicely for if
case. However it's not that clear how to implement logical operations like &&
and ||
. If I type the following to online llvm compiler:
void main1(bool r, bool y) {
bool l = y || r;
}
最后几行完全让我感到困惑:
Last several lines completely confuse me:
; <label>:10 ; preds = %7, %0
%11 = phi i1 [ true, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8
看起来像phi节点会产生可以使用的结果.而且我印象深刻的是,phi节点只是定义了来自哪个路径的值.
Looks like phi node produces a result which can be used. And I was under impression that phi node just defines from which paths values coming.
有人可以解释什么是Phi节点,以及如何用它实现||
吗?
Could someone explain what is a Phi node, and how to implement ||
with it?
推荐答案
A phi node is an instruction used to select a value depending on the predecessor of the current block (Look here to see the full hierarchy - it's also used as a value, which is one of the classes which it inherits from).
由于LLVM代码的SSA(静态单分配)样式的结构,因此必须有phi节点-例如,以下C ++函数
Phi nodes are necessary due to the structure of the SSA (static single assignment) style of the LLVM code - for example, the following C++ function
void m(bool r, bool y){
bool l = y || r ;
}
转换为以下IR :(通过clang -c -emit-llvm file.c -o out.bc
创建-然后通过llvm-dis
查看)
gets translated into the following IR: (created through clang -c -emit-llvm file.c -o out.bc
- and then viewed through llvm-dis
)
define void @_Z1mbb(i1 zeroext %r, i1 zeroext %y) nounwind {
entry:
%r.addr = alloca i8, align 1
%y.addr = alloca i8, align 1
%l = alloca i8, align 1
%frombool = zext i1 %r to i8
store i8 %frombool, i8* %r.addr, align 1
%frombool1 = zext i1 %y to i8
store i8 %frombool1, i8* %y.addr, align 1
%0 = load i8* %y.addr, align 1
%tobool = trunc i8 %0 to i1
br i1 %tobool, label %lor.end, label %lor.rhs
lor.rhs: ; preds = %entry
%1 = load i8* %r.addr, align 1
%tobool2 = trunc i8 %1 to i1
br label %lor.end
lor.end: ; preds = %lor.rhs, %entry
%2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]
%frombool3 = zext i1 %2 to i8
store i8 %frombool3, i8* %l, align 1
ret void
}
那么这里会发生什么呢?
与C ++代码不同,在LLVM IR中变量bool l
可以为0或1,必须一次定义.因此,我们检查%tobool
是否为真,然后跳转到lor.end
或lor.rhs
.
So what happens here?
Unlike the C++ code, where the variable bool l
could be either 0 or 1, in the LLVM IR it has to be defined once. So we check if %tobool
is true, and then jump to lor.end
or lor.rhs
.
在lor.end
中,我们终于有了||的值.操作员.如果我们是从入口处到达的,那是对的.否则,它等于%tobool2
的值-这正是我们从以下IR行获得的结果:
In lor.end
we finally have the value of the || operator. If we arrived from the entry block - then it's just true. Otherwise, it is equal to the value of %tobool2
- and that's exactly what we get from the following IR line:
%2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]
这篇关于PHI指令的确切作用以及如何在LLVM中使用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!