В LLVM есть инструкция phi с довольно странным объяснением:
Команда 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 и как его реализовать ||
?
phi
Узел представляет собой решение задачи в компиляторах для преобразования ИК в «Статический сингл назначения» форме. Чтобы лучше понять решение, я предлагаю лучше понять проблему. Итак, я расскажу вам " Почемуphi
узел ".Ответы:
Узел phi - это инструкция, используемая для выбора значения в зависимости от предшественника текущего блока (посмотрите здесь, чтобы увидеть полную иерархию - он также используется как значение, которое является одним из классов, от которых он наследуется).
Узлы Phi необходимы из-за структуры стиля SSA (static single assignment) кода LLVM - например, следующая функция C ++
переводится в следующий IR: (создается через
clang -c -emit-llvm file.c -o out.bc
- и затем просматриваетсяllvm-dis
)Так что здесь происходит? В отличие от кода C ++, где переменная
bool l
может иметь значение 0 или 1, в LLVM IR ее нужно определять один раз . Итак, мы проверяем,%tobool
правда ли, а затем переходим кlor.end
илиlor.rhs
.В
lor.end
конце концов мы имеем значение из || оператор. Если приехали из въездного блока - значит, это правда. В противном случае оно равно значению%tobool2
- и это именно то, что мы получаем из следующей ИК-линии:источник
Вам вообще не нужно использовать фи. Просто создайте кучу временных переменных. Проходы оптимизации LLVM позаботятся об оптимизации временных переменных и будут использовать для этого phi node автоматически.
Например, если вы хотите сделать это:
Для этого вы можете использовать phi node (в псевдокоде):
Но можно обойтись без phi node (в псевдокоде):
При выполнении проходов оптимизации с llvm этот второй код будет оптимизирован для первого кода.
источник