LLVM ma instrukcję phi z dość dziwnym wyjaśnieniem:
Instrukcja „phi” służy do implementacji węzła φ na grafie SSA reprezentującym funkcję.
Zwykle jest używany do implementacji rozgałęziania. Jeśli dobrze zrozumiałem, jest to potrzebne, aby umożliwić analizę zależności, aw niektórych przypadkach może pomóc uniknąć niepotrzebnego ładowania. Jednak nadal trudno jest zrozumieć, co dokładnie robi.
Przykład Kalejdoskopu wyjaśnia to całkiem dobrze na potrzeby if
przypadku. Jednak nie jest tak jasne, jak zaimplementować operacje logiczne, takie jak &&
i ||
. Jeśli wpiszę następujące polecenie do kompilatora online llvm :
void main1(bool r, bool y) {
bool l = y || r;
}
Ostatnie kilka wierszy całkowicie mnie zmyliło:
; <label>:10 ; preds = %7, %0
%11 = phi i1 [ true, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8
Wygląda na to, że węzeł phi daje wynik, który można wykorzystać. Miałem wrażenie, że węzeł phi po prostu określa, z których ścieżek przychodzą wartości.
Czy ktoś mógłby wyjaśnić, czym jest węzeł Phi i jak go zaimplementować ||
?
phi
Węzeł jest rozwiązanie tego problemu w celu przekształcenia kompilatorów IR w „statyczne pojedyncze przypisanie” formie. Aby lepiej zrozumieć rozwiązanie, sugerowałbym lepsze zrozumienie problemu. Więc powiem ci " Dlaczegophi
węzeł ".Odpowiedzi:
Węzeł phi to instrukcja służąca do wybierania wartości w zależności od poprzednika bieżącego bloku (spójrz tutaj, aby zobaczyć pełną hierarchię - jest również używany jako wartość, która jest jedną z klas, z których dziedziczy).
Węzły Phi są niezbędne ze względu na strukturę stylu SSA (static single assignment) kodu LLVM - na przykład poniższa funkcja C ++
zostanie przetłumaczony na następujący IR: (utworzony przez
clang -c -emit-llvm file.c -o out.bc
- a następnie przeglądanyllvm-dis
)Więc co się tutaj dzieje? W przeciwieństwie do kodu C ++, w którym zmienna
bool l
może mieć wartość 0 lub 1, w LLVM IR musi być zdefiniowana raz . Sprawdzamy więc, czy%tobool
jest prawdą, a następnie przechodzimy dolor.end
lublor.rhs
.W
lor.end
końcu mamy wartość || operator. Jeśli przyjechaliśmy z bloku wejściowego - to po prostu prawda. W przeciwnym razie jest równa wartości%tobool2
- i dokładnie to otrzymujemy z następującej linii IR:źródło
W ogóle nie musisz używać phi. Po prostu utwórz kilka tymczasowych zmiennych. Przebiegi optymalizacji LLVM zajmą się optymalizacją zmiennych tymczasowych i automatycznie użyją do tego węzła phi.
Na przykład, jeśli chcesz to zrobić:
Możesz do tego użyć węzła phi (w pseudokodzie):
Ale możesz obejść się bez węzła phi (w pseudokodzie):
Uruchamiając przebiegi optymalizacji z llvm, ten drugi kod zostanie zoptymalizowany do pierwszego kodu.
źródło