Matt Godbolt, l'auteur originel de Compiler Explorer nous apprend sur son blog que l'outil a atteint 10 ans le 22 mai 2022.
Compiler Explorer est un site web sur lequel l'utilisateur peut écrire un programme et observer l'assembleur généré par le compilateur. Il s'agit d'un logiciel libre, écrit en JavaScript, et disponible sous les termes du contrat BSD-2-clause.
Il s'agissait initialement d'un petit outil développé sur son temps libre pour trouver des réponses à des questions d'optimisations réalisées par le compilateur. Depuis, le service est toujours le même, à ceci près qu'il répond maintenant aux questions de milliers de développeurs sur de nombreux langages et compilateurs !
Entre temps l'outil a évolué et est capable d'afficher l'assembleur généré par différents compilateurs (GCC et Clang bien sûr, mais aussi ICC, ICX, MSVC et plein d'autres), et dans plusieurs versions. Il sait même afficher l'IR LLVM quand -emit-llvm
est passé à Clang.
Le site s'est aussi étendu vers le support de plus de trente autres langages. On y trouve du C et du C++, mais aussi du Java, Pascal, Kotlin, Rust, Python…
Tout cela n'aurait pu être possible sans de nombreux contributeurs et soutiens, que Matt n'oublie pas de nommer dans son post :
- Partouf, développeur et administrateur du site ;
- Rubén, un des premiers gros contributeurs ;
- Jason Turner, qui a grandement participé à la popularisation de Compiler Explorer en l'utilisant dans ses présentations ;
- Austin, un autre administrateur qui s'occupe aussi de la sécurité du site et du bac à sable ;
- Mats, Marc et Jeremy, les plus récents commiteurs ;
- Nicole, Tim et Dale de Microsoft pour avoir ajouté le support des compilateurs basés sur Windows ;
- Luka et Chedy pour l'amitié, les conversations et les conseils durant ces années ;
- et enfin sa femme et ses enfants pour apporter leur soutien et accepter qu'il soit occupé avec son loisir bizarre.
Aller plus loin
- Compiler Explorer (382 clics)
- Le post sur le blog de l'auteur (42 clics)
- Code source (38 clics)
- Une présentation de Compiler Explorer par Matt Godbolt à CppCon 2019 (37 clics)
# Quelques (petites) précisions :)
Posté par Marc (site web personnel) . Évalué à 7.
Matt a effectivement fait ça "sur du temps libre"… mais à son travail, c'est pour cela qu'il remercie son employeur de l'époque d'avoir accepté de publier librement le code (yoohoo).
Et s'il est vrai qu'au début, il s'agissait uniquement de voir l'assembleur émit par GCC, maintenant, c'est bien bien plus large:
- IR des compilateurs (tree/ipa/rtl de GCC, LLVM-IR, rustc HIR, GNAT Tree, d'autres) (d'ailleurs, pas besoin de passer
-emit-llvm
, c'est gérer par l'app qui l'affiche dans une fenêtre à part)- compilation + édition de lien et affichage du code désassemblé
- exécution (x86_64 seulement sur le site public) du programme
- utilisation d'outils sur le résultat (pahole, readelf, …)
- outils d'analyse (OSACA, LLVM-MCA)
Il y a un mode IDE/Tree qui permet de gérer plusieurs fichiers, le support de CMake, la possibilité de faire des "diff" des sorties, support de bibliothèques (Boost, …), fonction magique permettant de faire
#include
sur une URL, …# Cas d'usage
Posté par PierreLM . Évalué à 4.
Si certains d'entre vous utilisent ce logiciel, je suis curieux d'en savoir plus sur les cas d'usage possible.
Je suis développeur Java, j'ai l'impression que ça correspond à des cas poussés à l'extrême. Si c'est n'est pas vrai, je serais très heureux d'en apprendre plus !
[^] # Re: Cas d'usage
Posté par Marc (site web personnel) . Évalué à 9.
Quelques cas me concernant:
- tester un bout de code étrange "qui ne devrait même pas compiler" et voir ce que ça donne
- mettre au point une petite fonction isolée
- échanger un bout de code avec qq1
- tester la présence d'un bug dans un compilateur en fonction des version (conformance view est très utile)
- debug du backend de GCC avec la visualisation des sorties RTL. La possibilité de faire des diff permet de "trouver" la version de GCC ou l'option qui va changer le code généré (et pointer vers l'endroit à gratter)
- regarder ce qui sort du frontend Rust de GCC dans la première sortie de l'IR
generic
- comparer le code émit pour le même code/compilateur mais avec options différentes
- très pratique pour éplucher/étudier des bugs (le bugzilla de GCC a souvent des liens pointant vers des exemples pour reproduire)
[^] # Re: Cas d'usage
Posté par barmic 🦦 . Évalué à 1.
Si l'objet c'est d'avoir un bout de code avec l'assembleur que tu veux c'est pas plus logique d'écrire l'assembleur directement ?
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Cas d'usage
Posté par Thomas Douillard . Évalué à 3.
Tu peux vouloir mettre au point pour que ce soit optimal sur des plateformes différentes ?
[^] # Re: Cas d'usage
Posté par barmic 🦦 . Évalué à 2.
Tu peux écrire l'assembleur pour chacune d'entre elles et fallback sur du c.
Si tu as en tête le code assembleur que tu veux ton source devrait être l'assembleur à mon humble avis et pas un code C qui va être potentiellement non idiomatique avec un commentaire dessus "j'ai vérifié gcc X.Y génère le code assembleur qui va bien (du moins avec les options qu'on utilise sur la version a.b.c)".
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Cas d'usage
Posté par Thomas Douillard . Évalué à 2.
Oui ça se fait, c'est assez lourd. J'imagine que ça se justifie de pas s'encombrer avec ça si c'est "suffisamment bon" sur toutes les plateformes.
[^] # Re: Cas d'usage
Posté par Marc (site web personnel) . Évalué à 4. Dernière modification le 31 mai 2022 à 09:37.
Oui et non. Parfois tu préfères quand même que ça soit du C, ça reste plus portable que de l'assembleur. Il arrive que de modifier un peu le code C permette à certaines optim de mieux fonctionner… J'ai pas de cas en tête, mais quand tu commences à avoir des boucles, des pointeurs, etc, c'est pas rare que ça freine pas mal le compilateur. Tu peux le constater dans l'assembleur (code sous optimal car manque de connaissance du compilo par ex), ou dans les passe d'optim qui t'informent du pourquoi elles ne font rien. Tu modifies le code (par ex en donnant/corrigeant des info de type, du restrict, changeant l'imbrication des boucles, …) et tu peux voir si ça va mieux. Le but n'est pas toujours de trouver le code C qui donnera le code ASM que tu as en tête. Sans compter que ce code devra être maintenu/porté. Souvent, ça guide aussi vers du code plus propre, plus lisible (j'ai bien dit parfois… parfois, c'est l'inverse).
Et parfois, c'est mieux de faire un bout d'asm, aussi. Je n'ai pas l'impression qu'il existe une solution parfaite à tous les cas :) CE vient aider pour certains cas, pas tous.
Cas particulier: debug de la description cible dans GCC: tu cherches à ce que le backend émette une instruction particulière.. Avoir CE qui te permet de facilement donner des petits coups de tournevis, ça aide à chercher.
PS/Edit: et il n'y a pas que le C non plus, même si on l'oubli un peu.
[^] # Re: Cas d'usage
Posté par barmic 🦦 . Évalué à 3.
Je comprends ton point de vu et je suis d'accord qu'il n'y a pas de règle universelle.
En fait c'est ça qui me semble fragile. Tu te base sur un comportement de compilateur qui dans une version avec les paramètres que tu utilise produit quelque chose, mais ça n'est pas une garantie que ce soit pérenne. De plus tu écris du code avec une part d'implicite qui ne se voit qu'avec la version asm du code. Devoir ajouter et maintenir un commentaire peut être plus subtile.
Mais j'attire juste attention on est d'accord.
Ma remarque tiens sur tout langage. Si tu écris dans un langage haut niveau en ayant en tête ce que ta toolchain va produire exactement ton langage de haut niveau génère plus de bruit de part le fait qu'il t'oblige à retrouver les abstractions qui vont bien et nécessite une phase de compilation ensuite.
Dis autrement le code devrait être au plus proche de ce que l'on pense, si on pense en assembleur c'est ça que l'on devrait commiter.
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Cas d'usage
Posté par claudex . Évalué à 4.
Ça me semble aussi vrai avec l'assembleur, tu peux avoir des instructions supplémentaire ou un comportement différent avec une nouvelle génération de processeur (ou un autre fabricant). Alors que si le comportement est compris par le compilateur, il l'améliorera en fonction de la nouvelle cible.
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: Cas d'usage
Posté par barmic 🦦 . Évalué à 3.
Dans une certaine mesure mais de manière bien plus légère. Il s'agit d'une abstraction plus simple, il me semble qu'elle est bien moins altérée.
Mais c'est surtout une question de la dernière phrase de mon commentaire :
https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll
[^] # Re: Cas d'usage
Posté par Julien Jorge (site web personnel) . Évalué à 4.
Au boulot on utilise la stratégie que tu décris. Nous avons environ 30 000 lignes d'assembleur (en utilisant des intrinsèques, ce qui est quand même plus pratique que l'assembleur brut) et la principale motivation est d'avoir ces fonctions aussi optimisées que possible. Le meilleur moyen d'y arriver est de les écrire avec les instructions que nous voulons voir dans le binaire. Le cadre est assez fixe cela dit puisque nous visons un seul couple architecture/compilateur.
Nous avons aussi une version C pour chaque fonction optimisée, à la fois comme fallback mais aussi comme référence pour la version assembleur.
En pratique on remarque que certains compilateurs arrivent à émettre de l'assembleur équivalent à celui écrit à la main depuis fonctions C. Ce n'était pas le cas avec de plus anciennes versions.
Perso je trouve qu'il nous manque quelque chose pour mesurer le gain apporté par les fonctions optimisées, pour voir si elles sont toujours pertinentes. Nous avons des mesures globales, qui englobent toutes les optims, mais rien individuellement. J'ai bien entamé un truc à base de Google Benchmark mais ce n'est pas évident d'avoir un test représentatif des cas d'utilisation réels.
[^] # Re: Cas d'usage
Posté par KuroLightning . Évalué à 2.
Je correspond assez bien avec ce que tu décris (assembleur intrinsic…)
Pour répondre à ta dernière partie, j'utilise llvm-mca (dispo avec compiler explorer dans la section add tools) pour avoir une idée théorique des performances en asm (par exemple en deux versions). Sinon pour les mesures fines, j'utilise perf avec les compteur hardware ou parfois du rdtsc (ça dépend des cas et de ce que je veux mesurer).
[^] # Re: Cas d'usage
Posté par Firwen (site web personnel) . Évalué à 4.
Je l'utilise régulièrement et ce n'est pas du tout réservé pour des cas extrêmes:
Quelques cas d'utilisation dans le désordre:
Vérifier le support d'une fonctionnalité d'un langage sur plusieurs compilateurs
Prototyper très rapidement une idée et l'envoyer à quelqu'un pour une demo / revue.
tester la portabilité d'un snippet de code sur plusieurs plateformes / OS / compilateur
Vérifier la vectorization / inlining d'un bout de code sur un ensemble de compilateur.
Tester l'impacte en terme de code généré / performance d'un flag de compilateur.
Et beaucoup d'autre.
Il n'y a rien qui ne peut pas être fait sans compiler explorer, mais c'est un trés bon tool qui rend simplement plus productif.
[^] # Re: Cas d'usage
Posté par xryl669 . Évalué à 3.
En C++ récent, le code devient très vite cryptique, d'autant plus qu'il faut contourner les interprétation fallacieuse du standard par les différents compilateurs.
Pour cela, il y a cppinsights.io qui explique comment un meta programme est interprété (compris) par le compilateur.
Cela permet d'écrire du code template plus robuste, plus complet et plus lisible parfois.
[^] # Re: Cas d'usage
Posté par Julien Jorge (site web personnel) . Évalué à 3.
Je l'utilise le plus souvent pour confirmer que le compilateur va bien effectuer certaines optims (genre éviter d'appeler systématiquement une fonction dans une boucle quand son résultat ne dépend pas de l'itération).
Le deuxième cas d'utilisation que j'ai est de comparer les sorties de différents compilateurs.
Et de temps en temps c'est aussi juste pour être impressionné par les transformations d'optimisation.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.