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 всегда помещайте инструкцию установки флага непосредственно перед инструкцией условного перехода (если она является одной из простых, перечисленных в таблице ниже), чтобы они могли слиться в один поток в декодерах.

Делать это не намного хуже для старых процессоров, которые не выполняют макрослияние. Установка флагов раньше может сократить штраф за неверный прогноз ветки на единицу для таких процессоров, поскольку позволяет быстрее обнаружить ошибочный прогноз. У меня нет эталонных тестов, но я не думаю, что небольшой недостаток все более редких процессоров оправдывает упущение преимуществ переднего плана по пропускной способности (декодирование и выдача) для процессоров, которые объединяют. Общая пропускная способность UOP часто может быть узким местом.

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

Из справочника по микроарху Agner Fog, таблица 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,

(В противном случае они не сливаются в макрос, и вы добавляете дополнительный моп для объединения флагов (например, когда вы читаете eax после написания al). Или на более ранних процессорах с частичной остановкой флагов.)

Core2 / Nehalem были более ограничены в возможностях макро-слияния (только для CMP/TEST с более ограниченными комбинациями JCC), и Core2 вообще не мог макро-плавить в 64-битном режиме.

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

Другие вопросы по тегам