LLVM有phi指令,但解释很奇怪:
'phi‘指令用于在表示函数的SSA图中实现φ节点。
通常,它用于实现分支。如果我理解正确的话,它需要使依赖分析成为可能,在某些情况下,它可以帮助避免不必要的加载。然而,仍然很难理解它到底是做什么的。
对于if
案例,万花筒example很好地解释了这一点。然而,如何实现像&&
和||
这样的逻辑操作还不是很清楚。如果我在online llvm编译器中输入以下内容:
void main1(bool r, bool y) {
bool l = y || r;
}
最后几行完全把我搞糊涂了:
; <label>:10 ; preds = %7, %0
%11 = phi i1 [ true, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8
看起来phi节点生成了一个可以使用的结果。我的印象是,phi节点只定义了来自哪些路径的值。
有人能解释一下什么是Phi节点,以及如何用它实现||
吗?
发布于 2012-07-15 01:42:00
phi节点是一条指令,用于根据当前块的前身选择值(查看here可以看到完整的层次结构-它也用作一个值,这是它继承的类之一)。
由于LLVM代码的SSA (静态单一赋值)样式的结构,需要使用Phi节点-例如,下面的C++函数
void m(bool r, bool y){
bool l = y || r ;
}
翻译成以下IR:(通过clang -c -emit-llvm file.c -o out.bc
创建,然后通过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中,变量bool l
可以是0或1,它必须定义为一次。因此,我们检查%tobool
是否为真,然后跳转到lor.end
或lor.rhs
。
在lor.end
中,我们最终得到了||运算符的值。如果我们是从入口块到达的,那么它就是真的。否则,它等于%tobool2
的值--这正是我们从下面的IR行得到的:
%2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]
发布于 2012-07-15 05:40:48
你根本不需要使用phi。只需创建一堆临时变量。LLVM优化过程将负责优化临时变量,并将自动使用phi节点。
例如,如果您想这样做:
x = 4;
if (something) x = x + 2;
print(x);
为此,您可以使用phi node (在伪代码中):
但是您可以不使用phi node (在伪代码中):
H122load x to temp x2
H130调用使用X4打印
通过使用llvm运行优化过程,第二个代码将被优化为第一个代码。
发布于 2022-01-29 02:17:46
现有的答案是好的。但是,我想让它更简单、更简短。
block3:
%result = phi i32 [%a, %block1], [%b, %block2]
这意味着如果前一个块为block1
,则选择value a
。如果上一个块为block2
,请选择value b
。
为什么我们要这样写呢?这是为了防止在两个不同的块中分配result
,例如if
块和else
块。因为,我们不想违反SSA原则。SSA帮助编译器应用各种优化,并且它是中间代码的事实标准。有关更多信息,请参阅this reference。
https://stackoverflow.com/questions/11485531
复制相似问题