gcc - 禁用 g++ 构建的所有 AVX-512 指令
问题描述
嗨,我正在尝试使用这些标志在没有任何 avx512 指令的情况下构建:
-march=native -mno-avx512f
. 但是我仍然得到一个vmovss
生成了 AVX512 ( ) 指令的二进制文件(我正在使用 elfx86exts 进行检查)。知道如何禁用这些吗?
解决方案
-march=native -mno-avx512f
是正确的选择,vmovss
只需要 AVX1。
有一个AVX512F EVEX 编码vmovss
,但 GAS 不会使用它,除非涉及的寄存器是xmm16..31
. 当您使用 禁用 AVX512F 时,GCC 不会使用这些寄存器发出 asm ,或者首先不使用类似or-mno-avx512f
的东西启用它。-march=skylake
-march=znver2
如果您仍然不确定,请检查实际的反汇编+机器代码以查看指令以什么前缀开头:
- a
C5
orC4
byte: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 源代码行上缺少标记。
推荐阅读
- mysql - 带条件和排序的 SQL 限制查询优化
- java - 如果我们使用前端 Angularjs 和后端 spring-boot,是否会被 CORS 策略处理阻止?
- javascript - 如何知道 Node.js 中的文件位置?- lseek 的返回值
- c - 如何让 ssize_t 输出复制的字节?
- flutter - Websocket重连循环,graphql_flutter
- java - Mysql对一组行的约束
- javascript - 草稿js在返回键上添加新块
- automation - 如何从 CYPRESS 中的多个通用规范运行特定的测试块,例如 SMOKE 和 REGRESSION 测试用例
- android - 当设备位于同一位置时,是否有任何 android java 代码可以停止 GPS 位置的移动?
- jekyll - 如何使用 Jekyll 编辑/更新大型网站上的文章