LLVM tem instrução phi com explicação bastante estranha:
A instrução 'phi' é usada para implementar o nó φ no gráfico SSA que representa a função.
Normalmente, é usado para implementar ramificações. Se bem entendi, é necessário para possibilitar a análise de dependências e, em alguns casos, pode ajudar a evitar carregamentos desnecessários. No entanto, ainda é difícil entender o que ele faz exatamente.
O exemplo do caleidoscópio explica muito bem para o if
caso. No entanto, não está claro como implementar operações lógicas como &&
e ||
. Se eu digitar o seguinte no compilador llvm online :
void main1(bool r, bool y) {
bool l = y || r;
}
As últimas linhas me confundem completamente:
; <label>:10 ; preds = %7, %0
%11 = phi i1 [ true, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8
Parece que o nó phi produz um resultado que pode ser usado. E fiquei com a impressão de que o nó phi apenas define de quais caminhos os valores vêm.
Alguém poderia explicar o que é um nó Phi e como implementar ||
com ele?
phi
nó é uma solução para o problema em compiladores para converter o IR na forma de "atribuição única estática". Para entender melhor a solução, sugiro entender melhor o problema. Então eu irei um acima de você " Por que é ophi
nó "Respostas:
Um nó phi é uma instrução usada para selecionar um valor dependendo do predecessor do bloco atual (Veja aqui para ver a hierarquia completa - também é usado como um valor, que é uma das classes da qual herda).
Os nós Phi são necessários devido à estrutura do estilo SSA (atribuição única estática) do código LLVM - por exemplo, a seguinte função C ++
é traduzido para o seguinte IR: (criado por meio de
clang -c -emit-llvm file.c -o out.bc
- e então visualizado por meiollvm-dis
)Então, o que acontece aqui? Ao contrário do código C ++, onde a variável
bool l
pode ser 0 ou 1, no LLVM IR ela deve ser definida uma vez . Portanto, verificamos se isso%tobool
é verdadeiro e, em seguida, vamos paralor.end
oulor.rhs
.Em
lor.end
nós finalmente temos o valor de || operador. Se chegamos do bloco de entrada - então é verdade. Caso contrário, é igual ao valor de%tobool2
- e é exatamente o que obtemos da seguinte linha de IR:fonte
Você não precisa usar phi. Basta criar um monte de variáveis temporárias. Os passos de otimização do LLVM cuidarão da otimização das variáveis temporárias e usarão o nó phi para isso automaticamente.
Por exemplo, se você quiser fazer isso:
Você pode usar o nó phi para isso (em pseudocódigo):
Mas você pode fazer sem o nó phi (em pseudocódigo):
Ao executar passos de otimização com llvm, este segundo código será otimizado para o primeiro código.
fonte