При использовании только 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
Вряд ли это того стоит, если вы действительно не хотите избежать возможности пропустить кэш-память для константы. В среднем нагрузка обычно выходит вперед.