禁用 g++ 构建的所有 AVX-512 指令

sas*_*has 1 x86 gcc g++ avx512

你好我试图建立一个没有任何avx512指令通过使用这些标志: -march=native -mno-avx512f。但是,我仍然得到一个二进制文件,其中vmovss生成了AVX512 ( ) 指令(我正在使用 elfx86exts 进行检查)。知道如何禁用这些吗?

Pet*_*des 6

-march=native -mno-avx512f是正确的选项,vmovss只需要 AVX1。

这里一个AVX512F EVEX编码vmovss,但除非涉及到的寄存器GAS不会使用它xmm16..31。使用这些寄存器时禁用AVX512F与GCC不会发出ASM -mno-avx512f,或与类似首位不启用-march=skylake-march=znver2

如果您仍然不确定,请检查实际的反汇编 + 机器代码以查看指令以什么前缀开头:

  • aC5C4字节:2 或 3 字节 VEX 前缀的开始,AVX1 编码。
  • 一个62字节:EVEX 前缀的开始,AVX512F 编码

例子:

.intel_syntax noprefix
vmovss xmm15, [rdi]
vmovss xmm15, [r11]
vmovss xmm16, [rdi]
Run Code Online (Sandbox Code Playgroud)

组装gcc -c avx.s和拆卸objdump -drwC -Mintel avx.o

0000000000000000 <.text>:
   0:   c5 7a 10 3f             vmovss xmm15,DWORD PTR [rdi]   # AVX1
   4:   c4 41 7a 10 3b          vmovss xmm15,DWORD PTR [r11]   # AVX1
   9:   62 e1 7e 08 10 07       vmovss xmm16,DWORD PTR [rdi]   # AVX512F
Run Code Online (Sandbox Code Playgroud)

10操作码前的 2 和 3 字节 VEX,以及 4 字节 EVEX 前缀。(ModRM 字节也不同;xmm0 和 xmm16 仅在来自前缀的额外寄存器位上有所不同,而不是 modrm)。

GASvmovss在可能的情况下使用 AVX1 VEX 编码和其他指令。 因此,您可以指望具有非 AVX512F 形式的指令尽可能使用非 AVX512F 形式。这就是 GNU 工具链(由 GCC 使用)的-mno-avx512f工作方式。

即使 EVEX 编码较短,这也适用。例如,当 a[reg + constant]可以使用 AVX512 缩放 disp8(按元素宽度缩放)但 AVX1 编码需要以字节计的 32 位位移时。

   f:   c5 7a 10 bf 00 01 00 00         vmovss xmm15,DWORD PTR [rdi+0x100]   # AVX1 [reg+disp32]
  17:   62 e1 7e 08 10 47 40    vmovss xmm16,DWORD PTR [rdi+0x100]           # AVX512 [reg + disp8*4]
  1e:   c5 78 28 bf 00 01 00 00         vmovaps xmm15,XMMWORD PTR [rdi+0x100]  # AVX1 [reg+disp32]
  26:   62 e1 7c 08 28 47 10    vmovaps xmm16,XMMWORD PTR [rdi+0x100]        # AVX512 [reg + disp8*16]
Run Code Online (Sandbox Code Playgroud)

请注意机器代码编码的最后一个字节或最后 4 个字节:它是 AVX1 编码的 32 位小端 0x100 字节位移,但 AVX512 编码的 8 位位移是 0x40 dwords 或 0x10 dqwords。

但是使用 asm-source 覆盖,{evex} vmovaps xmm0, [rdi+256]即使对于“低”寄存器,我们也可以获得紧凑的编码:

62 f1 7c 08 28 47 10    vmovaps xmm0,XMMWORD PTR [rdi+0x100]
Run Code Online (Sandbox Code Playgroud)

GCC 当然不会用-mno-avx512f.

不幸的是GCC和铛也错过优化时,你在编译时启用AVX512F,如__m128 load(__m128 *p){ return p[16]; }-O3 -march=skylake-avx512Godbolt)。使用二进制模式,或者只是注意在{evex}编译器输出的 asm 源代码行上缺少标记。