PHI指令的确切作用以及如何在LLVM中使用它 [英] What exactly PHI instruction does and how to use it in LLVM

查看:988
本文介绍了PHI指令的确切作用以及如何在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?

推荐答案

phi节点是用于根据当前块的前身选择值的指令(请参见

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.endlor.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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆