Основываясь на ответе анатолига, вы можете задаться вопросом , почему конструкция do-while более эффективна, особенно если учесть, что, как показано, тест был продублирован (поэтому сгенерированный код больше).Ответ заключается в том, что очень часто проверочное выражение всегда подтверждается при вводе в цикл, поэтому
if ( !test ) goto skip;
loop:
. . . // loop body
if ( !test ) goto loop;
skip:
. . . // continue the program
можно упростить до
loop:
. . . // loop body
if ( !test ) goto loop;
. . . // continue program
Теперь почему бы не сделать это вто же самое время, что и исходное преобразование, и избегать исходного преобразования, если компилятор не может доказать, что цикл будет повторяться хотя бы один раз?Потому что алгоритм, который доказывает цикл будет по крайней мере один раз, на самом деле является общим оптимизатором if-условия.Обычная последовательность оптимизаций выглядит примерно так:
- Преобразуйте все циклы в "каноническую" форму (более или менее, как показано в первом блоке кода выше)
- Делайте лоты имного оптимизаций, которые ожидают циклы в этой канонической форме, такие как показанное исключение оператора if.
- После того, как вы закончите со всем, что заботится о циклах как таковых, попытайтесь деканонизировать, где это устранит избыточность.
Еще одна вещь, которую нужно знать, это то, что иногда дублирующий тест преднамеренно оставляют, потому что компилятор ожидает, что это приведет к лучшему поведению во время выполнения.Например, если у компилятора есть основания полагать, что цикл обычно повторяется много раз, но не может доказать, что цикл всегда хотя бы один раз, тогда инструкция условного перехода вышецикл почти всегда провалится, а условная ветвь под циклом почти всегда будет прыгать.В таком случае их разделение может повысить точность предсказания ветвления ЦП.Точность предсказания ветвления уступает только удобству кэширования как ограничивающему фактору скорости на современных процессорах с ошибками.