Я читал различные руководства по оптимизации, которые утверждают, что ADD 1 быстрее, чем использование INC в x86. Это правда?
Действительно ли ADD 1 быстрее INC? x86
Ответ 1
На некоторых микроархитексах с некоторыми потоками команд INC
будет выполняться "остановка обновления частичных флагов" (поскольку он обновляет некоторые флаги, сохраняя остальные). ADD
устанавливает значение всех флагов и, следовательно, не рискует создать такой ларь.
ADD
не всегда быстрее, чем INC
, но он почти всегда по крайней мере такой же быстрый (на некоторых старых микроструктурах есть несколько угловых случаев, но они чрезвычайно редки), а иногда и значительно быстрее.
Подробнее см. Справочное руководство по оптимизации Intel или Заметки микро-архитектуры Agner Fog.
Ответ 2
Пока это не определенный ответ. Напишите этот файл C:
=== inc.c ===
#include <stdio.h>
int main(int argc, char *argv[])
{
for (int n = 0; n < 1000; n++) {
printf("%d\n", n);
}
return 0;
}
Затем запустите:
clang -march=native -masm=intel -O3 -S -o inc.clang.s inc.c
gcc -march=native -masm=intel -O3 -S -o inc.gcc.s inc.c
Обратите внимание на сгенерированный код сборки. Соответствующий вывод clang:
mov esi, ebx
call printf
inc ebx
cmp ebx, 1000
jne .LBB0_1
Соответствующий вывод gcc:
mov edi, 1
inc ebx
call __printf_chk
cmp ebx, 1000
jne .L2
Это доказывает, что как авторы clang, так и gcc считают, что INC
является лучшим выбором по сравнению с ADD reg, 1
на современных архитектурах.
Что бы это значило для вашего вопроса? Ну, я бы доверял их мнению в отношении руководств, которые вы прочитали, и пришел к выводу, что INC
работает так же быстро, как ADD
, и что один байт, сохраненный из-за более короткого кодирования регистра, делает его предпочтительным. Авторы компиляторов - это просто люди, поэтому они могут ошибаться, но это маловероятно.:)
Несколько экспериментов показывают, что если вы не используете опцию -march=native
, тогда gcc будет использовать add ebx, 1
. Clang otoh, всегда нравится лучше всего. Я пришел к выводу, что когда вы задавали вопрос в 2012 году, ADD
иногда предпочтительнее, но теперь в 2016 году вы всегда должны идти с INC
.
Ответ 3
В 80 или 90 простых временах выполнения команды в основном определялось количеством компонентов в команде: add ax, 1 содержит еще одну декодируемую единицу (немедленную) по сравнению с инк. ax или добавлением ax, bx. И, таким образом, 80286 потратил еще один такт на декодирование инструкции.
Тогда была/была эпоха, когда Intel особенно оптимизировала большинство инструкций типа RISC за счет инструкций типа CISC. (например, добавить ax, [mem]; добавить [mem], ax). Сегодня или, по крайней мере, завтра, они дешевы... Сложные последовательности ветвей будут разрешены в 30-конвейерном конвейере, который выполняет автоматическое переименование регистра.
Итак, теперь мы с большей вероятностью находимся в эпоху, где inc eax
- CISC, aka bad и add eax,1
- это RISC, что хорошо. Но эти вещи могут измениться в течение ночи.