Dans le prolongement de la réponse d'anatolyg, vous pouvez vous poser les questions suivantes pourquoi la construction do-while est plus efficace, surtout si l'on considère que, comme indiqué, le test a été dupliqué (le code généré est donc plus gros). La réponse est que très souvent, on peut prouver que l'expression de test est toujours vraie à l'entrée de la boucle, alors
if ( !test ) goto skip;
loop:
. . . // loop body
if ( test ) goto loop;
skip:
. . . // continue the program
peut être simplifié en
loop:
. . . // loop body
if ( test ) goto loop;
. . . // continue program
Maintenant, pourquoi ne pas faire cela en même temps que la transformation originale, et éviter la transformation originale si le compilateur ne peut pas prouver que la boucle va tourner au moins une fois ? Parce que l'algorithme qui prouve que la boucle effectuera au moins un cycle est en fait un optimiseur générique de condition if. La séquence habituelle d'optimisations est quelque chose comme ceci :
- Transformer toutes les boucles en une forme "canonique" (plus ou moins comme indiqué dans le premier bloc de code ci-dessus)
- Faites beaucoup d'optimisations qui s'attendent à des boucles sous cette forme canonique, comme l'élimination de l'instruction if présentée.
- Une fois que vous en aurez fini avec tout ce qui concerne les boucles en tant que telles, essayez de les décanoniser là où cela éliminerait la redondance.
L'autre chose à savoir est que parfois, un test en double est délibérément laissé en place parce que le compilateur s'attend à ce que cela produise un meilleur comportement à l'exécution. Par exemple, si le compilateur a des raisons de penser que la boucle généralement cycles de nombreuses fois, mais ne peut pas prouver qu'elle toujours au moins une fois, alors l'instruction de branchement conditionnel au-dessus de la boucle passera presque toujours, et le branchement conditionnel au-dessous de la boucle sautera presque toujours. Dans ce cas, le fait de les laisser séparées rendra probablement le prédicteur de branchement du processeur plus précis. La précision de la prédiction de branchement est, après la convivialité du cache, le facteur limitant la vitesse des processeurs modernes hors ordre.