LLVMはファイかなり奇妙な説明の指示:
「phi」命令は、関数を表す SSA グラフの φ ノードを実装するために使用されます。
通常、これは分岐を実装するために使用されます。私の理解が正しければ、依存関係の分析を可能にするために必要であり、場合によっては不要な読み込みを回避するのに役立つ可能性があります。ただし、それが正確に何をするのかを理解するのはまだ困難です。
万華鏡例は、ケースについてかなりうまく説明しています。しかしif
、 や のような論理演算をどのように実装するかは明確ではありません。次のように入力すると、&&
||
オンライン 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 ノードとは何か、また||
それをどのように実装するかを説明していただけますか?
ベストアンサー1
ファイノードは、現在のブロックの前のブロックに応じて値を選択するために使用される命令です(参照ここ完全な階層を表示するには、継承元のクラスの 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では次のように定義する必要があります。一度したがって、 が%tobool
真かどうかを確認し、 または にジャンプしlor.end
ますlor.rhs
。
では、lor.end
最終的に || 演算子の値が得られます。エントリ ブロック - から到達した場合は、単に true になります。それ以外の場合は、 - の値と等しくなります。これは、%tobool2
次の IR 行から取得される値とまったく同じです。
%2 = phi i1 [ true, %entry ], [ %tobool2, %lor.rhs ]