我有一个C程序,该程序只能在要编译代码的Ivy Bridge CPU上运行,在gcc 4.8上,我尝试使用-march=native
进行编译以利用CPU的所有特定指令。为了进行一些研究比较,我也希望以32位模式进行编译]
我已经以这种方式为x64编译了程序(请注意我在Linux x64上)
gcc -march=native -s -O2 mycode.c
并且分解代码,我可以看到使用了AVX指令集
并且以这种方式用于32位x86
gcc -m32 -march=native -s -O2 mycode.c
如果我尝试反汇编代码,则看不到任何AVX指令,指令集为Pentium Pro,80x87。类似于FP数学中的fld
/fadd
/ fstp
。添加-mavx
无效,结果相同。
我该如何解决?
-m32-m64-mx32
为32位或64位环境生成代码。 -m32选项将int,long和指针类型设置为32位,并生成可在任何i386系统上运行的代码。-m64选项将int设置为32位,将long和指针类型设置为64位,并为x86-64体系结构生成代码。对于达尔文,仅-m64选项还会关闭-fno-pic和-mdynamic-no-pic选项。
-mx32选项将int,long和指针类型设置为32位,并为x86-64体系结构生成代码。
您要使用AVX指令最接近-m32
的地方是使用-mx32
,但可能不是您想要的。
-m32
的默认值为-mfpmath=387
。
GCC4.8 将如果使用-O3 -m32 -march=native
进行编译,则使用AVX自动矢量化,但是要获得标量AVX数学,例如vmovss xmm0, DWORD PTR [edx+eax*4]
,也使用-mfpmath=sse
例如
void foo(float *arr){
for(int i=0;i<4096;i++){
arr[i] *= 2;
}
}
在Skylake-X上将on Godbolt with gcc4.8.5 -m32 -O2 -Wall -march=native
编译为此:
foo(float*):
mov edx, DWORD PTR [esp+4]
xor eax, eax
.L3:
fld DWORD PTR [edx+eax*4]
fadd st, st(0)
fstp DWORD PTR [edx+eax*4]
add eax, 1
cmp eax, 4096
jne .L3
rep ret
在-O3
,它使用x87进行标量介绍/清除,但在主循环中仍使用vaddps ymm
。
或使用-mfpmath=sse
-m32 -O2 -Wall -march=native
,我们将获得您可能期望的结果:
foo(float*):
mov edx, DWORD PTR [esp+4]
xor eax, eax
.L3:
vmovss xmm0, DWORD PTR [edx+eax*4]
vaddss xmm0, xmm0, xmm0
vmovss DWORD PTR [edx+eax*4], xmm0
add eax, 1
cmp eax, 4096
jne .L3
rep ret
我使用了-march=native
,因为gcc4.8.5对于-march=ivybridge
来说太旧了,我不想建议-march=corei7-avx
或它们曾经使用的任何愚蠢的名字。绝对不希望仅建议-mavx
启用AVX而无需设置调整选项,而是将其保留为-mtune=generic
。并且无法启用popcnt,BMI或您的CPU可能具有的其他任何功能。
BTW,-o2
将输出文件名设置为2
。 -s
生成一个剥离的二进制文件,几乎不需要您拆卸。