ファイ ノードは、現在のブロックの先行ノードに応じて値を選択するために使用される命令です (完全な階層を確認するには、ここを参照してください。継承元のクラスの 1 つである値としても使用されます)。
Phi ノードは、LLVM コードの SSA (静的単一割り当て) スタイルの構造のために必要です。たとえば、次の 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++ コードとは異なり、 LLVM IR では一度定義する必要があります。が trueかどうかを確認してから、 or%tobool
にジャンプします。lor.end
lor.rhs
lor.end
最終的に || の値が得られます。オペレーター。エントリーブロックから到着した場合、それは本当です。それ以外の場合は - の値に等しく、これは%tobool2
まさに次の IR 行から得られるものです。
%2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]