llvm libLLVMCore源码分析 11 - PHI Node Instruction

源码路径

llvm\include\llvm\IR\Instruction.h

llvm\include\llvm\IR\Instruction.def

llvm\include\llvm\IR\Instructions.h

llvm\include\llvm\IR\InstrTypes.h

llvm PHI Node

LLVM IR采用SSA(Static Single Assignment)的形式,这种形式的核心要求有2点:

  • 每个变量只被赋值1次。
  • 每个变量在使用前必须先定义。

如下源代码:

int foo(int x) {
        x = x - 3;
		x = x + 2;
        return x;
}

生成的SSA如下所示,可以看到同一个变量x在IR中变成了2个变量%sub和%add,分别对应两次赋值:

define dso_local i32 @foo(i32 %x) #0 {
entry:
  %sub = sub nsw i32 %x, 3
  %add = add nsw i32 %sub, 2
  ret i32 %add
}

SSA这种形式,在程序中存在分支的情况下,带来了1个问题:不确定该使用哪个变量。比如下列源代码:

int bar(int a) {
        int x;
        if (a) {
                x = a + 3;
        } else {
                x = a + 5;
        }
        int y = x + 3;
        return y;
}

生成的伪SSA:

define dso_local i32 @bar(i32 %a) #0 {
entry:
  %tobool = icmp ne i32 %a, 0
  br i1 %tobool, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %add = add nsw i32 %a, 3  ; x1 = a + 3
  br label %if.end

if.else:                                          ; preds = %entry
  %add1 = add nsw i32 %a, 5 ; x2 = a + 5
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %x.0 = ? ; x3 = x1 or x2?
}

为了解决这个问题,llvm在IR中引入了PHI Node,表示这种关系,可以看到实际生产的IR中,用%x.0 = phi i32 [ %add, %if.then ], [ %add1, %if.else ]表示了不同分支下的x的取值,其中的phi既PHI Node Instruction。

define dso_local i32 @bar(i32 %a) #0 {
entry:
  %tobool = icmp ne i32 %a, 0
  br i1 %tobool, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %add = add nsw i32 %a, 3
  br label %if.end

if.else:                                          ; preds = %entry
  %add1 = add nsw i32 %a, 5
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %x.0 = phi i32 [ %add, %if.then ], [ %add1, %if.else ]
  %add2 = add nsw i32 %x.0, 3
  ret i32 %add2
}

PHI Node Instruction

phi指令用于实现SSA中的PHI Node。

语法

<result> = phi [fast-math-flags] <ty> [ <val0>, <label0>], ...

参数说明:

ty:valx的类型。

语义

在运行时,phi指令通过当前BasicBlock的前继BasicBlock的label来匹配labelx,result等于对应的valx。

示例

Loop:       ; Infinite loop that counts from 0 on up...
  %indvar = phi i32 [ 0, %LoopHeader ], [ %nextindvar, %Loop ]
  %nextindvar = add i32 %indvar, 1
  br label %Loop

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值