AVX(2) 收集指令如何实际计算获取地址?

Hen*_*all 3 c++ simd intrinsics avx avx2

当前_mm_i32gather_epi32()的英特尔内在函数指南将每个子字的计算地址描述为:

addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
Run Code Online (Sandbox Code Playgroud)

最后8个让我困惑。假设addrbase_addr以字节为单位,并且scale取值为 1、2、4 或 8,那么您只能从基地址索引 8 个字节的步长。这是文档中的错误,还是我遗漏了什么?我检查过的所有收集指令的描述方式都是相同的。

上一个问题引用的文档没有 8,这表明某些内容已经发生了变化。

Pet*_*des 5

请注意伪代码中的下一行:

\n
dst[i+31:i] := MEM[addr+31:addr]\n
Run Code Online (Sandbox Code Playgroud)\n

显然有人认为将内存地址描述为位地址而不是字节地址是个好主意。/捂脸。这实际上没有意义,不是任何人所期望的,甚至没有做得正确,因为他们未能按base_addr8 缩放。所以他们在字节地址中添加了一个位偏移量。

\n

这只是糟糕的文档,并且是比链接问题中引用的先前版本更糟糕的描述方式。这只是文档更改,而不是代码含义的更改,您可以尝试编译它并查看 asm 以查看生成的实际指令。(我对您链接的问题的回答仍然是正确的:asm 指令允许比例因子为 1、2、4 或 8,作为 2 位移位计数的编码方式与标量指令对缩放索引寻址模式的编码方式相同。因此您可以使用字节偏移量向量。)

\n

以前更好的伪代码是:

\n
dst[i+31:i] := MEM[base_addr + SignExtend(vindex[i+31:i])*scale]\n
Run Code Online (Sandbox Code Playgroud)\n

因此MEM[](虚拟地址空间)使用计算出的字节偏移量进行索引,并且访问宽度是位dst[31:0]宽度隐含的 32 位。

\n
\n

根据经验,内联函数通常尽可能直接映射到汇编指令。 他们不会选择以要求编译器vpslld ymm0, ymm1, 3在运行之前发出缩放索引寄存器的方式来定义它vpgatherdd

\n

因此,您可以查阅 asm 指令的文档(有时有不同的伪代码,例如本例):https://www.felixcloutier.com/x86/vpgatherdd :vpgatherqd

\n
...\n    DATA_ADDR\xe2\x86\x90BASE_ADDR + (SignExtend(VINDEX1[i+31:i])*SCALE + DISP;\n    IF MASK[31+i] THEN\n        DEST[i +31:i]\xe2\x86\x90FETCH_32BITS(DATA_ADDR); // a fault exits the instruction\n    FI;\n
Run Code Online (Sandbox Code Playgroud)\n