LLVM a une instruction phi avec une explication assez étrange:
L'instruction 'phi' est utilisée pour implémenter le nœud φ dans le graphe SSA représentant la fonction.
Il est généralement utilisé pour implémenter le branchement. Si j'ai bien compris, il est nécessaire de rendre l'analyse des dépendances possible et dans certains cas, cela pourrait aider à éviter un chargement inutile. Cependant, il est encore difficile de comprendre ce qu'il fait exactement.
L' exemple de Kaléidoscope l' explique assez bien pour le if
cas. Cependant, la manière d'implémenter des opérations logiques telles que &&
et ||
. Si je tape ce qui suit dans le compilateur llvm en ligne :
void main1(bool r, bool y) {
bool l = y || r;
}
Les dernières lignes me confondent complètement:
; <label>:10 ; preds = %7, %0
%11 = phi i1 [ true, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8
On dirait que le nœud phi produit un résultat qui peut être utilisé. Et j'avais l'impression que le nœud phi définit simplement de quels chemins les valeurs proviennent.
Quelqu'un pourrait-il expliquer ce qu'est un nœud Phi et comment l'implémenter ||
?
phi
nœud est une solution du problème dans les compilateurs pour convertir l'IR en forme «d'affectation unique statique». Pour comprendre mieux comprendre la solution, je suggérerais de mieux comprendre le problème. Donc, je vais vous dire " Pourquoi est lephi
nœud ".Réponses:
Un nœud phi est une instruction permettant de sélectionner une valeur en fonction du prédécesseur du bloc courant (Regardez ici pour voir la hiérarchie complète - il est également utilisé comme valeur, qui est l'une des classes dont il hérite).
Les nœuds Phi sont nécessaires en raison de la structure du style SSA (affectation unique statique) du code LLVM - par exemple, la fonction C ++ suivante
est traduit dans l'IR suivant: (créé via
clang -c -emit-llvm file.c -o out.bc
- puis visualisé viallvm-dis
)Alors que se passe-t-il ici? Contrairement au code C ++, où la variable
bool l
peut être 0 ou 1, dans LLVM IR, elle doit être définie une fois . Nous vérifions donc si%tobool
c'est vrai, puis passons àlor.end
oulor.rhs
.Dans
lor.end
nous avons enfin la valeur du || opérateur. Si nous sommes arrivés du bloc d'entrée - alors c'est juste vrai. Sinon, il est égal à la valeur de%tobool2
- et c'est exactement ce que nous obtenons de la ligne IR suivante:la source
Vous n'avez pas du tout besoin d'utiliser phi. Créez simplement un tas de variables temporaires. Les passes d'optimisation LLVM se chargeront d'optimiser les variables temporaires et utiliseront automatiquement le nœud phi pour cela.
Par exemple, si vous souhaitez faire ceci:
Vous pouvez utiliser le nœud phi pour cela (en pseudocode):
Mais vous pouvez vous passer du nœud phi (en pseudocode):
En exécutant des passes d'optimisation avec llvm, ce deuxième code sera optimisé pour le premier code.
la source