Continuons cette série sur les codes fantastiques avec un code exceptionnel et inattendu
Lors d’une relecture de code autour de l’attribut [[likely]] (introduit en C++20 pour marquer le test d’une branche qui a de fortes chances de s’évaluer à vrai), je me suis rendu compte d’un choix amusant fait par le compilateur Clang quand il compile une branche qui lève une exception. Mais commençons par le commencement. Le code suivant :
est traduit par Clang (avec le drapeau -O2) en l’assembleur que voici :
Cet agencement du code favorise le cas où val est vrai (exécution plus rapide, car pas de sauts, meilleure localité dans le cache d’instruction, etc.).
Cependant, si au lieu de retourner la valeur produite par bar, on l’utilise pour lever une exception :
Le compilateur considère que la branche qui lève une exception est... exceptionnelle, donc peu probable et il favorisera alors l’autre branche, et il génère alors l’assembleur suivant :
On peut rendre la branche vraie à nouveau plus probable en lui attachant l’attribut [[likely]] et notre exception redevient plus probable, ce qui reste un peu contraire à l’usage canonique d’une exception :
Il reste intéressant de voir que le compilateur Clang possède une heuristique de prédiction de branchement pour le traitement des exceptions, et qu’on peut reprendre la main tout en restant sur des attributs standard ! Pour les curieux, je vous laisse tester GCC sur le même code, les heuristiques sont différentes :-).