[C] pow(expr,2) vs. expr*expr

Je demande plus pour ma compréhension que pour une optimisation plus ou moins utilie.
Pour l’instant on est d’accord que faire x*x évite d’appeler la fonction pow() donc on gagne du temps. A partir de puissance3, ça devient long à écrire et à relire, l’utilisation de pow se justifie j’imagine.

Question:
Que se passe t’il si on a A+B à élever au carré?
Dans ce cas, pow(A+B,2) devient logiquement plus interessant que (A+B)*(A+B) qui demande 2 fois le même calcul.
Je me suis dit, y a qu’à faire
tmp = A+B;
tmp *= tmp;

Dans le cas de gros calculs scientifiques, je me retrouve parfois avec plusieurs variables temporaires. C’est galère et pas très lisible.

En faisant des recherches, j’ai lu une histoire d’optimisation lors de la compilation. Le compilateur rajouterait lui même cette vriable temporaire?
Si c’est le cas, pas besoin de variable temporaires à la main? Il suffit de balancer les expressions en pâtés sans s’inquièter des doublons de calculs?
Qu’en est’il des langages interprétés matlab ou même bash?

Pour t’aider à faire de plus amples recherches, ce type d’optimisation s’appelle du common subexpressions elimination. GCC l’utilise quand l’optimisation est active (-O2 / -O3 / -Os à ma connaissance) mais comme toujours ce n’est pas parfait. Tant que les sous-expressions communes ne se rapportent qu’à des variables et constantes il peut optimiser, pour les fonctions c’est beaucoup moins clair : que se passe-t-il quand une sous-expression commune provoque un effet de bord (affichage etc) ? Comment distinguer une fonction avec et sans effet de bord, surtout si cette fonction se situe dans une autre unité de compilation ?
Les cas varient beaucoup, sachant que le compilateur est contraint de conserver la sémantique originale du code source. Donc dans le doute, il n’optimise pas.

Si tu veux forcer une optimisation, crée la variable temporaire toi-même, au moins tu seras sûr.

Pour tester gcc possède une fonctionnalité très pratique :

test.s va contenir le code assembleur avec en commentaire le code C.

Bonjour,

Pour ma part je te conseillerais :

  • si tu travailles sur des nombres flottants, d’utiliser la fonction pow()
  • si tu travailles sur des entiers, de créer une fonction carre() qui fait le boulot :

int carre(int nb) { return nb*nb; }

Si jamais tu veux économiser un appel de fonction, tu peux essayer d’utiliser le mot clé inline mais tu abandonnes la compatibilité c89. Et il me semble que le compilateur “inline” tout seul un appel de fonction si ça lui semble opportun.

Dans tous les cas, si tu fais un truc illisible tu te tire une balle dans le pied.

Merci à tous (toutes? :116 ) les trois.
@syam: Voila, je saurai où chercher. En attendant d’avoir tout compris, je continue à la main. C’est un peu comme sous Debian (tu connais?), tu peux faire les choses à ta sauce et en plus c’est instructif.
@Misterfreez: J’avais vu un truc similaire où un mec postait le code assembleur obtenu avec pow(x,2). Ca donnait:
movsd (%rsi), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, (%rsi)
donc pas d’appel de fnction. Très pratique ta commande mais je galère à lire le résultat par rapport à l’exemple précédent (trop d’info, je réessaierai avec un programme plus simple)
@branch: C’est rare que d’autres personnes aient à relire mon code donc je fais en fonction de mes critères de lisibilité. J’ai de toute façon tendance à tartiner de commentaires dès que j’écris ue magouille.

Bonjour

Le plus rapide n’est il pas d’appliquer alors l’algorithme de horner pour des polynômes.