ファイノードは、現在のブロックの先行ノードに応じて値を選択するために使用される命令です(ここを見てください)完全な階層を確認するには、を参照してください。これは、継承元のクラスの1つである値としても使用されます)。
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
}
では、ここで何が起こるのでしょうか?変数bool l
が0または1のいずれかであるC ++コードとは異なり、LLVMIRでは一度定義する必要があります。したがって%tobool
、trueかどうかを確認してから、lor.end
またはにジャンプしlor.rhs
ます。
ではlor.end
、私たちは最終的にの価値を持っている|| オペレーター。エントリーブロックから到着した場合、それは本当です。それ以外の場合は、%tobool2
-の値に等しくなります。これは、次のIRラインから得られるものです。
%2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]
phi
ノードは、「静的単一代入」形にIRを変換するコンパイラで問題の解です。解決策をよりよく理解するには、問題をよりよく理解することをお勧めします。だから私はあなたに「なぜphi
ノードなのか」を1つ挙げます。