В SSE3 инструкция PALIGNR выполняет следующее:
PALIGNR объединяет операнд назначения (первый операнд) и исходный операнд (второй операнд) в промежуточную композицию, сдвигает композицию с байтовой гранулярностью вправо на постоянную немедленную и извлекает результат выравнивания по правому краю в место назначения.
Сейчас я в процессе переноса своего кода SSE4 для использования инструкций AVX2 и работы над 256-битными регистрами вместо 128-битных.
Наивно полагал, что встроенная функция _mm256_alignr_epi8
(VPALIGNR) выполняет ту же операцию, что и _mm_alignr_epi8
только для 256-битных регистров. К сожалению, это не совсем так. Фактически, _mm256_alignr_epi8
обрабатывает 256-битный регистр как 2 128-битных регистра и выполняет 2 операции «выравнивания» в двух соседних 128-битных регистрах. Эффективно выполняет ту же операцию, что и _mm_alignr_epi8
, но на 2 регистрах одновременно. Это наиболее четко показано здесь: _mm256_alignr_epi8
В настоящее время мое решение состоит в том, чтобы продолжать использовать _mm_alignr_epi8
, разделив регистры ymm (256bit) на два регистра xmm (128bit) (high и low), например:
__m128i xmm_ymm1_hi = _mm256_extractf128_si256(ymm1, 0);
__m128i xmm_ymm1_lo = _mm256_extractf128_si256(ymm1, 1);
__m128i xmm_ymm2_hi = _mm256_extractf128_si256(ymm2, 0);
__m128i xmm_ymm_aligned_lo = _mm_alignr_epi8(xmm_ymm1_lo, xmm_ymm1_hi, 1);
__m128i xmm_ymm_aligned_hi = _mm_alignr_epi8(xmm_ymm2_hi, xmm_ymm1_lo, 1);
__m256i xmm_ymm_aligned = _mm256_set_m128i(xmm_ymm_aligned_lo, xmm_ymm_aligned_hi);
Это работает, но должен быть лучший способ, верно?
Существует ли, возможно, более «общая» инструкция AVX2, которую следует использовать для получения того же результата?