avx2寄存器位反转

Joh*_*ith 2 c++ x86 simd avx2

是否有(快速)方法在avx2寄存器中执行32位int值的位反转?例如

_mm256_set1_epi32(2732370386); 
<do something here>
//binary: 10100010110111001010100111010010 => 1001011100101010011101101000101
//register contains 1268071237 which is decimal representation of 1001011100101010011101101000101
Run Code Online (Sandbox Code Playgroud)

har*_*old 6

由于我找不到合适的傻瓜,我会发布它.

这里的主要思想是pshufb利用并行的16项表查找来反转每个半字节的位.反转字节很明显.在每个字节中反转两个半字节的顺序可以通过将其构建到查找表(保存移位)或通过明确地移动低部分半字节(保存LUT)来完成.

这样的东西总共未经测试:

__m256i rbit32(__m256i x) {
    __m256i shufbytes = _mm256_setr_epi8(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12);
    __m256i luthigh = _mm256_setr_epi8(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15, 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15);
    __m256i lutlow = _mm256_slli_epi16(luthigh, 4);
    __m256i lowmask = _mm256_set1_epi8(15);
    __m256i rbytes = _mm256_shuffle_epi8(x, shufbytes);
    __m256i high = _mm256_shuffle_epi8(lutlow, _mm256_and_si256(rbytes, lowmask));
    __m256i low = _mm256_shuffle_epi8(luthigh, _mm256_and_si256(_mm256_srli_epi16(rbytes, 4), lowmask));
    return _mm256_or_si256(low, high);
}
Run Code Online (Sandbox Code Playgroud)

在循环中的典型上下文中,应该提升这些负载.

好奇的Clang使用了4次shuffle,它重复了第一次shuffle.