LLVM memiliki instruksi phi dengan penjelasan yang cukup aneh:
Instruksi 'phi' digunakan untuk mengimplementasikan node φ dalam grafik SSA yang mewakili fungsi tersebut.
Biasanya digunakan untuk mengimplementasikan percabangan. Jika saya mengerti dengan benar, itu diperlukan untuk membuat analisis ketergantungan mungkin dan dalam beberapa kasus dapat membantu untuk menghindari pemuatan yang tidak perlu. Namun masih sulit untuk memahami apa yang dilakukannya.
Contoh Kaleidoskop menjelaskannya dengan cukup baik untuk if
kasus. Namun tidak begitu jelas bagaimana mengimplementasikan operasi logis seperti &&
dan ||
. Jika saya mengetik berikut ini ke compiler llvm online :
void main1(bool r, bool y) {
bool l = y || r;
}
Beberapa baris terakhir benar-benar membingungkan saya:
; <label>:10 ; preds = %7, %0
%11 = phi i1 [ true, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8
Sepertinya node phi menghasilkan hasil yang bisa digunakan. Dan saya mendapat kesan bahwa phi node hanya menentukan dari mana nilai jalur berasal.
Bisakah seseorang menjelaskan apa itu simpul Phi, dan bagaimana menerapkannya ||
?
phi
simpul merupakan solusi dari masalah di compiler untuk mengkonversi IR menjadi "Static tunggal tugas" bentuk. Untuk memahami lebih baik tentang solusi, saya sarankan untuk lebih memahami masalahnya. Jadi saya akan memberi tahu Anda " Mengapaphi
node ".Jawaban:
Node phi adalah instruksi yang digunakan untuk memilih nilai tergantung pada pendahulu dari blok saat ini (Lihat di sini untuk melihat hierarki penuh - ini juga digunakan sebagai nilai, yang merupakan salah satu kelas yang diwarisi darinya).
Node phi diperlukan karena struktur gaya SSA (penugasan tunggal statis) dari kode LLVM - misalnya, fungsi C ++ berikut
diterjemahkan ke dalam IR berikut: (dibuat melalui
clang -c -emit-llvm file.c -o out.bc
- dan kemudian dilihat melaluillvm-dis
)Jadi apa yang terjadi disini? Tidak seperti kode C ++, di mana variabel
bool l
bisa berupa 0 atau 1, di LLVM IR harus ditentukan sekali . Jadi kami memeriksa apakah%tobool
benar, dan kemudian melompat kelor.end
ataulor.rhs
.Dalam
lor.end
kami akhirnya memiliki nilai || operator. Jika kami tiba dari blok masuk - maka itu benar. Jika tidak, itu sama dengan nilai%tobool2
- dan itulah yang kami dapatkan dari garis IR berikut:sumber
Anda tidak perlu menggunakan phi sama sekali. Buat saja banyak variabel sementara. Pass pengoptimalan LLVM akan menangani pengoptimalan variabel sementara dan akan menggunakan node phi untuk itu secara otomatis.
Misalnya, jika Anda ingin melakukan ini:
Anda dapat menggunakan node phi untuk itu (dalam pseudocode):
Tetapi Anda dapat melakukannya tanpa node phi (dalam pseudocode):
Dengan menjalankan pengoptimalan lewat dengan llvm, kode kedua ini akan dioptimalkan ke kode pertama.
sumber