В SSE3 команда PALIGNR выполняет следующее:
PALIGNR объединяет операнд назначения (первый операнд) и исходный операнд (второй операнд) в промежуточный составной элемент, сдвигает композит на гранулярность байта вправо постоянной константой и извлекает выровненный по правому краю результат в место назначения.
В настоящее время я занимаюсь переносом моего кода SSE4 для использования инструкций AVX2 и работы с 256-битными регистрами вместо 128 бит.
Наивно, я полагал, что функция intrinsics _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 (256 бит) на два xmm (128 бит) регистра (высокий и низкий), например:
__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, которая должна использоваться для получения того же результата?