gcc:-march=native 和 -march=<特定架构> 之间的差异

Ste*_*mer 8 gcc cpu-architecture compiler-optimization

为了比较各种-march设置将启用哪些标志,我正在比较以下命令的输出,如本 SO 答案中所述:

$ gcc -Q -march=native         --help=target
$ gcc -Q -march=skylake-avx512 --help=target
Run Code Online (Sandbox Code Playgroud)

请注意,为避免产生疑问,使用检测到的-march=native拱门输出为skylake-avx512

$ gcc -Q -march=native --help=target | grep march
  -march=                           skylake-avx512
Run Code Online (Sandbox Code Playgroud)

两个变体输出的大多数标志-march完全匹配。

但是,存在一些差异:

$ diff <(gcc -Q -march=native --help=target) <(gcc -Q -march=skylake-avx512 --help=target)
12c12
<   -mabm                               [enabled]
>   -mabm                               [disabled]
119c119
<   -mpku                               [disabled]
>   -mpku                               [enabled]
136c136
<   -mrtm                               [enabled]
>   -mrtm                               [disabled]
138c138
<   -msgx                               [disabled]
>   -msgx                               [enabled]
Run Code Online (Sandbox Code Playgroud)

正是这些差异促使我提出这个问题。

如何-march=native选择启用和禁用哪些指令集?

我有如下猜想:

  • -march=native将使用 CPUID 指令来计算支持的指令集等,以便检测处理器变体
  • -march=foobar将使用处理器支持的指令集的硬编码列表foobar

如果这是正确的,那么我可以看到两种可能的解决方式:

选项1:

可能-march=native无法 100% 正确,而当发布新处理器时,支持的指令集表会更新,并且更有可能是正确的。

因此我们期望-march=foobar成为“更正确”的标志。

选项2:

-march=native将使用 CPUID 指令来计算支持的指令集 - 因此保证是正确的,而-march=foobar将使用可能不正确的硬编码指令集列表。

因此我们期望-march=native成为“更正确”的标志。

如果选项 2正确,人们可以推测 using-march=foobar可能最终会启用不受支持的指令集 - 并且如果程序发出这些指令会导致崩溃。

到目前为止,我还没有成功地找到上述任何一个或任何一个是否正确的答案。

如果我想针对特定架构,请确保启用所有(且仅)受支持的指令集,并且无法使用-march=native,那么最好的方法是什么?