在 AVX2/ymm 寄存器中混洗 3 位值的有效方法

dam*_*boy 9 c sse simd avx avx2

我有一个有趣的问题,想不出用矢量化代码解决的有效方法。

我有一个ymm包含 8 个 32 位整数的寄存器,其中每个整数由以下部分组成:

  • 低 24 位是8x 个3bit“个体”值
  • 8位包含一个 3位值,“无关”这个问题,但最好我会保持这个值不变,而不会影响3位值。我可以3自由地在前 8 位内移动那个位值,但我想理想地保留在那里的某个地方......

我想要做的是找到一种方法来“转置”3 位值,以便(显示前 3 个元素):

Legend: 
z -> 8 Top-level bits I'd like to keep in place/don't care about)
a..x -> groups of 3-bit values I'd like to transpose over the ymm register
vvvv Source vvvv
-----------------
|MSB                          LSB|MSB                          LSB|MSB                          LSB|...
|zzzzzzzz...............cccbbbaaa|zzzzzzzz...............kkkjjjiii|zzzzzzzz...............sssrrrqqq|...
|zzzzzzzz...............qqqiiiaaa|zzzzzzzz...............rrrjjjbbb|zzzzzzzz...............ssskkkccc|...
-----------------
^^^^ Dest ^^^^
Run Code Online (Sandbox Code Playgroud)

我可以执行 8x( extract+ pdep+ vmovq+ vpmovzxbd+ vpslld+ vpor) 操作,大致如下:

Legend: 
z -> 8 Top-level bits I'd like to keep in place/don't care about)
a..x -> groups of 3-bit values I'd like to transpose over the ymm register
vvvv Source vvvv
-----------------
|MSB                          LSB|MSB                          LSB|MSB                          LSB|...
|zzzzzzzz...............cccbbbaaa|zzzzzzzz...............kkkjjjiii|zzzzzzzz...............sssrrrqqq|...
|zzzzzzzz...............qqqiiiaaa|zzzzzzzz...............rrrjjjbbb|zzzzzzzz...............ssskkkccc|...
-----------------
^^^^ Dest ^^^^
Run Code Online (Sandbox Code Playgroud)

但这是执行转置的大约 6x8 指令。我想认为我可以用 AVX2 实现一些神奇的东西,它可以使这种事情变得更短/更快,但我现在无法想出任何东西,如果有人对我有什么指导的话可以做不同的,我会很感激。