Действительно ли 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, что хорошо. Но эти вещи могут измениться в течение ночи.