gcc cpp asm
Optimisation C++/Assembleur par l'exemple
Posted by Jean-Michel Frouin on .Suite à la recopie de mon document sur les optimisations en C++, j'ai eu envie de rejouer avec l'assembleur (ici x86) pour démontrer les notions exposées dans ce document.
Avant tout il faut savoir, comment, demander à gcc de nous compiler un fichier source en assembleur. Cela passe par le paramètre -S :
gcc -S file.cxx
Produira le fichier file.s en assembleur.
Maintenant comparons l'assembleur produit par trois sources assez proche :
int main() { int a=2; a=a<<2; return 0; }
int main() { int a=2; a=a*4; return 0; }
int main() { int a=2; a=a*3; return 0; }
Et comparons l'assembleur produit (on ne garde que les parties non communes aux trois sources assembleur):
.file "mult1.cxx" sall $2,-4(%rbp)
.file "mult2.cxx" sall $2,-4(%rbp)
.file "mult3.cxx" movl -4(%rbp),%edx movl %edx,%eax addl %eax,%eax addl %edx,%eax movl %eax,-4(%rbp)
On se rend bien compte de deux choses :
- Pour le compilateur gcc/x86, il à fait l'optimisation lui même (Mais à moins de vérifier, il vaut mieux la faire nous dans le code plutôt que de partir du principe que le compilateur le fera pour nous) de remplacer la multiplication d'un facteur de 2 par un décalage de bit a gauche.
- Que le fait de ne pas avoir décomposé la multiplication par 3 en décalage d'un bit à gauche plus une fois a, à générer un code qui va consommer beaucoup plus de cycle CPU que s'y nous l'avions fait. (nous gagnerons à priori une instruction assembleur, pas plus sur cet exemple simple)
Allez, faisons le test :
int main() { int a=2; a=a<<1+a; return 0; }
movl -4(%rbp),%eax addl $1,%eax movl %eax,%ecx sall %cl,-4(%rbp)
Voila, l'homme triomphe encore de la machine :)