При использовании только SSE2 загрузка полного шаблона из памяти, как правило, является лучшим вариантом.
В исходном коде NASM вы можете использовать times 16 db 0x20
для облегчения обслуживания.
С SSE3 вы можете выполнять 8-байтовые широковещательные загрузки с помощью movddup
. С AVX вы можете выполнить 4-байтовую широковещательную загрузку с помощью vbroadcastss
. Эти широковещательные нагрузки очень хороши для современных ЦП, работают на только порте загрузки и не нуждаются в перетасовке. т.е. они так же дешевы, как movaps
на ЦП, которые поддержите их, за исключением байта или еще двух кодовых размеров. То же самое для регистров vbroadcastf128
в YMM.
Большинство компиляторов, кажется, не понимают этого и будут распространять константу через _mm_set1
, даже если это приводит к 32-байтовой константе вместо 4 байтов, даже если просто mov...
загружает ее перед циклом, а не складывает ее в операнд памяти для инструкция ALU. (И это все еще возможно с широковещательной загрузкой, когда доступен AVX512.) Clang иногда действительно использует широковещательную загрузку для простых констант.
AVX2 добавляет vpbroadcastb/w/d/q
, но только dword и qword являются чисто загрузочными мопами. Для широковещательной загрузки байтов и слов требуется перетасовка uop ALU, поэтому для постоянных байтовых шаблонов вы, вероятно, захотите просто широковещательно загрузить двойное слово, которое повторяет байт 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
. См. Какая лучшая инструкция последовательности для генерации векторных констант на лету? и руководство Агнера Фога.
Этот шаблон нелегко создать. Это байтовый шаблон (не слово, двойное слово или qword), и сдвиги SSE доступны только с детализацией по словам в лучшем случае. Однако, если мы знаем, что биты, смещенные по границам байтов, равны 0, все в порядке. например
pcmpeqd xmm0, xmm0 ; set1( -1 )
pabsb 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
Вряд ли это того стоит, если вы действительно не хотите избежать возможности промаха кеша для константы. В среднем вперед обычно выходит груз.
person
Peter Cordes
schedule
29.03.2020
times
илиdup
, чтобы упростить ввод. Вы также можете определить макрос, если это вас раздражает. - person fuz   schedule 30.03.2020