本文主要说明在预编译阶段,gcc根据用户指定的参数或者默认参数,而选择定义的一些宏。
-march=cpu-type
指导生成符合指定体系结构CPU的指令,对于x86家族的CPU来说,主要是涉及部分SIMD指令的使用。
比如:
‘core2’:Intel Core 2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support.
‘broadwell’:Intel Broadwell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX and PREFETCHW instruction set support.
‘skylake’:Intel Skylake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC and XSAVES instruction set support.
-mtune=cpu-type
在不改变ABI和支持指令集同时,对生成的指令优化调整。-mcpu=cpu-type与该选项相同,已经废弃。
在性能优化时,上述两个选项是比较常用的两个优化指令的方法;而在一些使用场景中,在考虑到指令兼容性时,也常常使用到这两个编译选项。
当用户提供的二进制需要在不同的CPU体系结构上运行时,考虑到性能、兼容性,常常打开、关闭具体的某种指令集优化,比如SSE4.2、AVX、BMI2等,可以通过“-m-xxx”、“-mno-xxx”使能、去使能相应的指令集:
-mmmx -msse -msse2 -msse3 -mssse3 -msse4 -msse4a -msse4.1 -msse4.2 -mavx -mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mavx512vbmi -msha -maes -mpclmul -mclfushopt -mfsgsbase -mrdrnd -mf16c -mfma -mfma4 -mprefetchwt1 -mxop -mlwp -m3dnow -m3dnowa -mpopcnt -mabm -mbmi -mbmi2 -mlzcnt -mfxsr -mxsave -mxsaveopt -mxsavec -mxsaves -mrtm -mtbm -mmpx -mmwaitx -mclzero -mpku
另外还有一些指令集相关的选项,可以通过”gcc –target-help“命令在环境上查看。
详细可以参考gcc手册:https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/x86-Options.html#x86-Options
可以通过命令gcc -march=native -c -Q –help=target或“gcc -### -march=native /usr/include/stdlib.h”查看当前使能了哪些目标机相关的编译选项,比如:
qq@qq:~$ gcc -march=native -c -Q --help=target
The following options are target specific:
-m128bit-long-double [disabled]
-m16 [disabled]
-m32 [disabled]
-m3dnow [disabled]
-m3dnowa [disabled]
-m64 [enabled]
-m80387 [enabled]
-m8bit-idiv [disabled]
-m96bit-long-double [enabled]
-mabi= sysv
-mabm [enabled]
-maccumulate-outgoing-args [disabled]
-maddress-mode= short
-madx [enabled]
-maes [enabled]
-malign-data= compat
-malign-double [disabled]
-malign-functions= 0
-malign-jumps= 0
-malign-loops= 0
-malign-stringops [enabled]
-mandroid [disabled]
-march= broadwell
-masm= att
-mavx [enabled]
-mavx2 [enabled]
-mavx256-split-unaligned-load [disabled]
... ...
指定march为native时,gcc会根据本地环境上的cpu类型选择对应的体系架构,而且相应的支持的指令集打开;
而在指定了具体的arch之后,具体支持的SSE、AVX等之类的仍显示为[disable],并不是说不会使用这些指令,而是arch指定的cpu体系结构一致说明支持了,也就是不单独指定,也已经支持使用了。
在指定CPU体系架构时,在编译阶段会生成支持指令集的汇编代码,对性能会有一定的提升;而在未指定具体架构,或者指定为“native”时,可以通过下面的命令查看具体的体系结构信息:
qq@qq:~$ gcc -c -Q --help=target | grep march
-march= x86-64
qq@qq:~$ gcc -march=native -c -Q --help=target | grep march
-march= broadwell
qq@qq:~$ gcc -march=corei7 -c -Q --help=target | grep march
-march= corei7
qq@qq:~$
查看gcc定义的指令集相关的宏,确定当前cpu体系架构支持哪些扩展指令集,可以通过gcc -march=x86-64 -dM -E - < /dev/null命令查看:
qq@qq:~$ gcc -march=x86-64 -dM -E - < /dev/null | grep -i SSE
#define __SSE2_MATH__ 1
#define __SSE_MATH__ 1
#define __SSE2__ 1
#define __SSE__ 1
qq@qq:~$ gcc -march=native -dM -E - < /dev/null | grep -i SSE
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE2_MATH__ 1
#define __SSE_MATH__ 1
#define __SSE2__ 1
#define __SSSE3__ 1
#define __SSE__ 1
#define __SSE3__ 1
qq@qq:~$
性能优化时,选择匹配的CPU体系结构优化代码,使用增强指令;应用程序、lib库等二进制发布时,出于对运行环境中CPU体系结构的兼容性考虑等,一般均都会用到上述的一些编译选项。