onur (./100) :
Super précis (y). Ca se voit que tu connais bien la génération de code pour en parler.
Euh, c'est censé être ironique? Si oui, tu as tort. J'ai donné une définition aussi précise que possible. Les passes d'optimisation font toutes des transformations différentes. Par exemple, il y a de la Dead Code Elimination (DCE), de la Partial Redundancy Elimination (PRE) etc. Cf.
http://gcc.gnu.org/onlinedocs/gccint/Tree_002dSSA-passes.html et
http://gcc.gnu.org/onlinedocs/gccint/RTL-passes.html.
Je ne les connais pas non plus, il me semble que c'est justement ces representations intermédiaires qui font que gcc est super portable, mais moins efficace que les compilos d'intel et microsoft.
Et là, c'est toi qui montres ton ignorance. Aucun compilateur moderne ne travaille sans aucune représentation intermédiaire. L'assembleur fini est très difficile à optimiser convenablement (surtout quand l'allocation des registres a déjà été faite), il est beaucoup plus efficace d'optimiser une représentation intermédiaire en forme Static Single Assignment (SSA). GCC 4 a aussi introduit une telle représentation SSA, en plus de la représentation intermédiaire bas-niveau qu'ils avaient, c'était la grande nouveauté qui a marqué le passage à la version 4, et ils font des optimisations sur les deux représentations maintenant (d'abord sur la SSA, puis sur le code bas-niveau (mais la plupart des passes d'optimisation se passent avant l'allocation des registres)).
L'idée de la SSA:
* Chaque variable n'est affectée qu'une et une seule fois.
* Pour représenter les boucles, il y a une affectation spéciale, le "nœud phi":
x=PHI(<BB1,a>,<BB2,b>,<BB3,c>) veut dire:
x=a si l'exécution provient du basic block BB1,
x=b si elle vient de BB2,
x=c si elle vient de BB3.
Pour transformer une représentation classique en SSA, il suffit de numéroter les variables pour que chaque affectation affecte à un numéro particulier. Maintenant, pour les pointeurs et les tableaux, c'est plus compliqué (il y a des bidouilles genre les VDEF et VUSE de GCC), j'ai juste expliqué l'idée de base.
Ce qui est fait dans les compilateurs optimisés pour une machine particulière, c'est de faire en sorte que la représentation intermédiaire corresponde le mieux possible à l'architecture de la machine, alors que dans GCC, il y a un tradeoff entre modeler le target actuel ou l'abstraire. (Et non, les représentations intermédiaires de GCC et les passes d'optimisation qui opèrent là-dessus ne sont pas totalement indépendantes de la machine visée.)
La coloration de graphe pour les registres, c'est le plus important, car c'est l'endroit critique.
C'est le plus visible actuellement, mais quand tu auras fait ça, on verra plus clairement les déficiences (ou plutôt l'absence totale
) des optimisations.
Personne ne code une affectation à l'intérieur d'une boucle alors qu'elle pourrait etre à l'extérieur.
Il y a plusieurs raisons pour lesquelles cette logique ne convient pas. Citons juste un exemple: l'inlining. Certes, on peut s'en passer, mais du coup, si on optimise en vitesse (en taille, l'inlining est souvent contreproductif), on se retrouve à faire du copier-coller plutôt que d'écrire une fonction, ce qui donne vite du code absolument impossible à maintenir. Et l'inlining seul aboutit souvent à du code sous-optimal, comme justement les affectations à l'intérieur d'une boucle, si elles faisaient partie de la fonction inline! Donc les autres optimisations deviennent utiles rien que pour ça. Et il y a d'autres cas où les optimisations servent. Si tu veux que le programmeur fasse le boulot du compilateur, autant écrire directement en assembleur.
Et j'ai l'impression que le concept de
maintenabilité t'échappe complètement. Ce qui me donne cette impression, c'est à la fois la tête de ton propre code et des remarques naïves comme celle-ci.
S'il faut coder 5 ans pour gagner 3 octets, compte pas sur moi, ni les autres.
Et hop, donc tous tes discours sur l'optimisation "prévue pour plus tard" et puis "prévue pour la réecriture en C++" quand j'ai montré tous les endroits sous-optimaux dans l'ancien ETP en VB étaient du vapor, merci de confirmer.
Enfin, il faut dire que tu ne savais apparemment pas ce que c'est (cf. ton premier paragraphe), mais ça commence à devenir ridicule, quelqu'un qui travaille sur un compilateur pendant 2 années et ne sait pas ce qu'est une passe d'optimisation!
Déjà il ne s'agit pas de gagner 3 octets (sauf sur un Hello World
), mais des centaines d'octets, tu as l'air de sous-estimer de beaucoup l'importance des optimisations. Et ensuite, tu profiterais automatiquement de toutes ces optimisations (et aussi d'une allocation de registres prête à l'emploi) si tu transformais ton frontend en un frontend GCC. Ça te donnerait aussi une version PC presque en cadeau, il n'y aurait que la librairie runtime à coder en version PC. Ça ne fait "que" des mois que je te dis ça...