X86_64 - Условия сборки и выход из строя

Я не прошу дать оценку.

(Если бы это было так, я бы сделал это сам.)


Мой вопрос:

Я предпочитаю избегать косвенных/индексных адресов для удобства.

В качестве замены я часто использую немедленную, абсолютную или регистрационную адресацию.

Код:

; %esi has the array address. Say we iterate a doubleword (4bytes) array.
; %ecx is the array elements count
(0x98767) myloop:
    ... ;do whatever with %esi
    add $4, %esi
    dec %ecx
    jnz 0x98767;

Здесь у нас есть сериализованная комбо (dec и jnz), которая предотвращает надлежащее выполнение вне порядка (зависимость).

Есть ли способ избежать этого? (Я не эксперт по сборке).

Ответ 1

При оптимизации для процессоров Intel всегда устанавливайте инструкцию по настройке флага перед инструкцией условного перехода, чтобы они могли вставлять макросы в один уровень в декодерах. Это не значительно хуже для старых процессоров. Вы можете урезать штраф за неверное предсказание ветки на единицу для процессоров, которые не используют пары сравнения и ветвления с использованием макросов. В правильно спрогнозированном случае, один дополнительный op занимает пространство в буфере повторного заказа за один дополнительный цикл. Я не думаю, что любой из них оправдывает разделение инструкций сравнения и ветвления. Я думаю, что более высокая пропускная способность процессора на Intel более значительна.

AMD Bulldozer/Piledriver/Steamroller может слить test/cmp с любым jcc, но только test/cmp, а не с любыми другими инструкциями ALU. Так что определенно положите сравнение с ветвями.

Из руководство Agar Fog's, таблица 9.2 (для Sandybridge/Ivybridge):

First       | can pair with these  |  cannot pair with
instruction | (and the inverse)    |
---------------------------------------------
cmp         |jz, jc, jb, ja, jl, jg|   js, jp, jo
add, sub    |jz, jc, jb, ja, jl, jg|   js, jp, jo
adc, sbb    |none                  |
inc, dec    |jz, jl, jg            |   jc, jb, ja, js, jp, jo
test        | all                  |
and         | all                  |
or, xor, not, neg | none           |
shift, rotate     | none           |

Table 9.2. Instruction fusion

В принципе, inc/dec может использовать макро-предохранитель с jcc, пока условие зависит только от битов, которые были изменены с помощью inc/dec. (В противном случае они не являются макро-предохранителями, и вы получаете дополнительный uop, вставленный для слияния флагов (например, когда вы читаете eax после записи al). Или на более ранних процессорах, срыв частичных флагов.)

Core2/Nehalem был более ограничен в возможности макро-слияния, и Core2 не мог сглаживать макросы в режиме 64 бит.

Чтение Agner Fog, оптимизирующее asm и руководства C, тоже, если вы еще этого не сделали. Они полны необходимых знаний.