Установите регистр XMM для повторяющегося байтового шаблона (широковещательный постоянный байт) - PullRequest
2 голосов
/ 29 марта 2020

Я знаю, что мы можем сделать что-то подобное, чтобы переместить символ в регистр xmm:

movaps xmm1, xword [.__0x20]

align 16
.__0x20 db 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20

, но так как это процесс памяти, я хочу знать, есть ли лучший способ? (также я говорю о SSE2, а не о других типах SIMD ...)

я хочу, чтобы каждый байт регистра xmm1 был 0x20, а не только один байт ..

( Примечание редактора: это можно назвать трансляцией или сплатом.
Это то, что делает _mm_set1_epi8(0x20) intrinsi c.)

1 Ответ

4 голосов
/ 30 марта 2020

При использовании только SSE2 загрузка полного шаблона из памяти, как правило, является лучшим выбором.

В источнике NASM вы можете использовать times 16 db 0x20 для удобства обслуживания.


С SSE3 Вы можете делать 8-байтовые широковещательные загрузки с movddup. С AVX вы можете выполнять 4-байтовую широковещательную загрузку с vbroadcastss. Эти широковещательные нагрузки очень хороши на современных процессорах: они работают на просто порт загрузки, не требуя случайного изменения. то есть они точно такие же дешевые, как movaps на процессорах, которые поддерживать их, за исключением одного байта или еще двух кодов. То же самое для vbroadcastf128 для регистров YMM.

Большинство компиляторов, кажется, не осознают этого и будут выполнять постоянное распространение через _mm_set1, даже когда это приводит к константе 32 байта вместо 4 байтов, даже когда просто mov... загрузите его впереди всего oop, не складывая его в операнд памяти для инструкции ALU. (И это все еще возможно с широковещательной загрузкой, когда AVX512 доступен.) Clang иногда использует преимущества широковещательной загрузки для простых констант.

AVX2 добавляет vpbroadcastb/w/d/q, но только dword и qword являются чистыми мопами загрузки. Для широковещательной загрузки байтов и слов требуется ALU shuffle uop, поэтому для шаблонов с постоянными байтами вы, вероятно, захотите просто транслировать загрузку слова, которое повторяет байт 4 раза. (Если это не элемент из большой справочной таблицы, затем сожмите таблицу, используя широковещательную загрузку байтов или слов, или pmovsx загрузку с расширением знака или что-либо еще.)

AVX512 добавляет vpbroadcastb/w/d/e из целочисленного регистра , чтобы вы могли mov eax, 0x20202020 / vpbroadcastd xmm0, eax, если у вас AVX512VL.


С SSE2 потребуется не менее 2 инструкций, включая случайное использование ALU, например, и может не стоить этого.

    movd    xmm0, [const_4B]
    pshufd  xmm0, xmm0, 0

Некоторые повторяющиеся константы могут быть сгенерированы на лету в паре инструкций, начиная со всех с pcmpeqd xmm0,xmm0. См. Каковы наилучшие последовательности команд для генерации векторных констант на лету? и руководство Агнера Фога.

Этот шаблон не , по-видимому, прост в генерировании. Это шаблон байтов (не слово, слово или слово), а сдвиги SSE доступны только с гранулярностью слова в лучшем случае. Однако, если мы знаем, что биты, сдвинутые через границы байтов, равны 0, это нормально. например,

   pcmpeqd  xmm0, xmm0     ; set1( -1 )
   pavgb    xmm0, xmm0     ; set1_epi8(1)    SSSE3
   pslld    xmm0, 5        ; set1_epi8(1<<5)

; or with only SSE2, something even less efficient like shift / packsswb / shift

Вряд ли это того стоит, если вы действительно не хотите избежать возможности пропустить кэш-память для константы. В среднем нагрузка обычно выходит вперед.

...