_mm_movepi64_pi64
перемещается из регистров XMM в MMX. Невозможно сделать правильный выбор, если только вы не хотите добавить больше SIMD в регистры MMX, а в вашем коде не хватает регистров XMM.
Если вы хотите, чтобы биты были индексом массива или чем-то еще, они должны быть в регистре GP, в этом случае вы хотите SSE4.1 _mm_extract_epi8
.
Если вам нужно придерживаться SSE2, это самый быстрый способ получить байт 5 из xmm0
:
pextrw eax, xmm0, 2
movzx eax, ah
Итак, мы надеемся, что компилятор будет работать так:
(uint8_t)(_mm_extract_epi16(var, n/2) >> ((n%2) * 8))
Менее эффективным будет сдвиг на байты _mm_bsrli_si128
(psrldq
) для помещения нужного байта в младший байт регистра xmm, тогда movd
(_mm_extract_epi16(var, 0)
испускает movd
, а не pextrw r32, xmm, 0
, к счастью). Таким образом, вам не нужно делать ничего лишнего, если желаемый байт является нечетным байтом, который pextw оставил бы в старшей 8 результата. Все еще нет простого способа использовать это с индексом, который не является константой времени компиляции.
Хранение 16B в памяти и загрузка нужного вам элемента должны быть достаточно хорошими. (Что вы, вероятно, получите с помощью объединения, если компилятор не оптимизирует его до pextract
инструкции). Компилятор будет использовать расположение в стеке размером 16B. Таким образом, store-> load forwarding должен работать нормально в этом случае, поэтому задержка будет низкой. Если вам нужно два отдельных элемента в две отдельные целочисленные переменные, это, вероятно, лучший выбор, возможно, победив несколько pextrw