代码之家  ›  专栏  ›  技术社区  ›  jww avp

如何用epi32收集元素?[复制]

  •  -1
  • jww avp  · 技术社区  · 7 年前

    Intrinsic Guide 说:

    __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
    

    说明

    使用32位索引从内存中收集32位整数。32位 vindex中的每个32位元素(每个索引按 比例)。收集的元素被合并到dst中。刻度应为1、2、4 或者8。

    操作

    FOR j := 0 to 3
      i := j*32
      dst[i+31:i] := MEM[base_addr + SignExtend(vindex[i+31:i])*scale]
    ENDFOR
    dst[MAX:128] := 0
    

    如果我能正确分析 vindex scale )索引是 base_addr 用于创建 __m128i result .

    val = arr[1] << 96 | arr[5] << 64 | arr[9] << 32 | arr[13] << 0

    $ cat -n gather.cxx
     1  #include <immintrin.h>
     2  typedef unsigned int u32;
     3  int main(int argc, char* argv[])
     4  {
     5          u32 arr[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
     6          __m128i idx = _mm_set_epi32(1,5,9,13);
     7          __m128i val = _mm_i32gather_epi32(arr, idx, 1);
     8          return 0;
     9   }
    

    但当我检查的时候 val :

    (gdb) n
    6               __m128i idx = _mm_set_epi32(1,5,9,13);
    (gdb) n
    7               __m128i val = _mm_i32gather_epi32(arr, idx, 1);
    (gdb) n
    8               return 0;
    (gdb) p val
    $1 = {0x300000004000000, 0x100000002000000}
    

    看来我在用 vindex公司 不正确。看来我在选择指数 1,2,3,4 .

    如何使用 vindex公司 规模 1,5,9,13 ?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Peter Cordes    7 年前

    数组元素的宽度为4字节。因此 在VSIB寻址模式下使用元素索引而不是字节偏移。

    这个 int const* base_addr int ,但是 在任何情况下,C指针都不能用它来计算 . 它直接输入到asm指令,因此需要处理字节偏移量。(希望也能处理严格的别名,以防您想从 uint64_t[] char[] )也可以是 const void* .

    如果内部函数将你的比例因子乘以4,你就不能在字节偏移量上使用它, 具有 内景 指数。asm指令可以按1、2、4或8进行缩放,使用通常的x86寻址模式编码:2位移位计数。


    跨距为4的跨距索引从1开始,除每个元素的高字节外,其他地方都会得到零。i、 它从数组的开始偏移1个字节,x86是little-endian。

    没有 得到 1,2,3,4 ,你有 1<<24 , 2<<24 ,等等。打印为一个大的64位整数使其更难被发现。

    1 -> 4

    (gdb) p  $xmm7.v4_int32
    $2 = {13, 9, 5, 1}
    

    __m128i 变量而不知道它在哪个寄存器中。