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

问题描述

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

addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8

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

A previous question 引用了没有那个 8 的文档,这表明某些事情已经发生了变化。

解决方法

注意伪代码中的下一行:

dst[i+31:i] := MEM[addr+31:addr]

显然有人认为将内存地址描述为位地址而不是字节地址是个好主意。 /面掌。这真的没有意义,不是任何人所期望的,甚至没有做对,因为他们未能将 base_addr 缩放 8。所以他们向字节地址添加了一个位偏移量。

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

之前更好的伪代码是:

dst[i+31:i] := MEM[base_addr + SignExtend(vindex[i+31:i])*scale]

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


根据经验,内在函数通常尽可能直接映射到 asm 指令。他们不会选择以需要编译器发出 {{1} } 在运行 vpslld ymm0,ymm1,3 之前缩放索引寄存器。

所以你可以查阅 asm 指令的文档(有时会有不同的伪代码,就像在这种情况下):https://www.felixcloutier.com/x86/vpgatherdd:vpgatherqd

vpgatherdd

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...