lscpu 和 cpuid 说我有 AVX2,但 vpsllvw 不起作用

lscpu and cpuid say I have AVX2, but vpsllvw does not work

如果我 运行 lscpu 或查看 /proc/cpuinfo,他们都说我的处理器支持 AVX2。

$ lscpu | grep -o avx2
avx2

然而,当我在我的代码中使用 vpsllvw 时,它给出了 SIGILL。

bits 64
global main
section .text
main:
        movdqa xmm0, [initial]
        vpsllvw xmm0, [shift]
        ret


section .data
        align 16
        initial dw 0,1,2,3,4,5,6,7
        shift dw 4,0,4,0,4,0,4,0

$ nasm -g -felf64 test.asm && g++ -g -m64 test.o

组装

我知道要处理的信息不多,但我能想到的就这些了。

处理器为英特尔酷睿 i5-7200U

解决方案

原来AVX2只有dword和qword版本,vpsllvw是AVX512

vpsllVw 需要 AVX512。 AVX2 只有 dword / qword 每元素变量计数移位。(并且只有双字用于算术右移。vpsravq 也需要 AVX512。)旋转也需要 AVX-512 : vprord / vprorvd 等等。

这个问题的初始版本是关于 vpsllw,可追溯到 MMX/SSE2 的指令的 AVX 形式(对所有元素使用相同的计数,从寄存器底部开始或内存位置,或作为立即数)。这就是下面的部分。


对于未来遇到其他 vpsllw / vpslld / vpsllq 问题的读者(或 VPSLLDQ 随机播放),也许您使用了 vpsllw 的形式(具有立即计数和内存源数据)需要 AVX-512VL,而您的 CPU 没有。

  • AVX1/2(VEX 前缀)允许 vpsllw xmm1, xmm2, imm8(AVX2 允许 ymm)
  • AVX512(EVEX 前缀)允许 vpsllw xmm1, xmm2/mem, imm8,数据来自内存。当然还有 ymm/zmm 形式。
  • AVX1/2和AVX512允许vpsllw xmm1, xmm2, xmm3/mem128(从内存操作数的低64位开始计数)。

因此 vpsllw xmm1, [rdi], 1 只能使用 EVEX 前缀进行编码,默认情况下 NASM 不会停止或警告您。

(如果你想阻止自己不小心使用 CPU 功能,YASM 可以使用 CPU skylake AMD 指令来做到这一点(AMD 包含 x86-64 的东西;这不是一个很好的设计系统)。但 YASM 根本不支持 AVX-512 最后我检查过,所以这只适用于之前的东西,不适用于各种级别的 AVX-512。我认为也有一些支持 NASM,也许有宏包。GAS 可以使用命令行选项进行 CPU 功能检查。)


我不知道为什么英特尔选择 而不是 允许 AVX1/2 立即计数形式的加载和移位内存源。该限制似乎完全是任意的,并且没有机器代码编码的原因说明它会成为一个问题。它使用 ModRM 中的 r/m 字段对只读源操作数 (the "D" row on the operand-encoding table for that instruction's manual entry) 进行编码,与 EVEX 形式相同,因此将内存源设为非法而不是允许它似乎是一个武断的决定. (r 字段是额外的操作码位,VEX VVVV 字段是目标寄存器。)

可能是在设计 Sandybridge 之前他们正在规划 AVX 时的某种历史原因?由于遗留 SSE 转移永远无法转移内存,因此 Nehalem CPU 内部结构不必支持为这种 uop 提供内存源。似乎是一个站不住脚的借口,而且自从 Sandybridge 最终显着重新设计了内部 uop 格式后,他们可能并没有得到太多好处。

存在类似形式的 imul reg, [mem], imm 指令,尽管它使用 ModRM /r 作为目标 reg,而不是额外的操作码位(这就是它如何使用 VEX 进行编码)。所以也许没有指令使用/r作为额外的操作码位,使用ModRM:r/m作为只读源操作数可以是内存?

shl dword [rdi], 4 这样的常规标量移位使用 r/m 作为读写操作数(/r 是额外的操作码位),就像许多单操作数 8086 指令一样,例如 neg dword [rdi],因此从 /r 解码内存操作数以及额外的操作码位是解码器已经必须处理的事情。

引入任意意想不到的限制似乎是糟糕的设计,破坏了使用允许内存源操作数的紧凑机器码格式作为 CISC 的意义。幸运的是,他们使用 AVX-512 解决了这个问题,但这会导致在您不打算或不期望的情况下意外使用 AVX-512 的可能性。