首页 > 解决方案 > 禁用 g++ 构建的所有 AVX-512 指令

问题描述

嗨,我正在尝试使用这些标志在没有任何 avx512 指令的情况下构建: -march=native -mno-avx512f. 但是我仍然得到一个vmovss生成了 AVX512 ( ) 指令的二进制文件(我正在使用 elfx86exts 进行检查)。知道如何禁用这些吗?

标签: gccx86g++avx512

解决方案


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

一个AVX512F EVEX 编码vmovss,但 GAS 不会使用它,除非涉及的寄存器是xmm16..31. 当您使用 禁用 AVX512F 时,GCC 不会使用这些寄存器发出 asm ,或者首先不使用类似or-mno-avx512f的东西启用它。-march=skylake-march=znver2

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

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

例子:

.intel_syntax noprefix
vmovss xmm15, [rdi]
vmovss xmm15, [r11]
vmovss xmm16, [rdi]

组装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

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

GAS 尽可能使用 AVX1 VEX 编码vmovss和其他指令。 因此,您可以指望具有非 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]

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

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

62 f1 7c 08 28 47 10    vmovaps xmm0,XMMWORD PTR [rdi+0x100]

GCC 当然不会对-mno-avx512f.

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


推荐阅读