有多少GCC优化级别?

有多少GCC优化级别?,c,optimization,gcc,compiler-construction,C,Optimization,Gcc,Compiler Construction,有多少优化级别 我试过gcc-O1、gcc-O2、gcc-O3和gcc-O4 如果我使用一个非常大的数字,它将不起作用 然而,我已经试过了 gcc -O100 它被编译了 有多少优化级别?四(0-3):参见GCC 4.4.2。任何更高的值都只是-O3,但在某一点上,您将超出可变大小限制。为了学究式的理解,您可以为gcc提供8种不同的有效-O选项,尽管有些选项的含义相同 该答案的原始版本说明有7个选项。此后,GCC增加了-Og,使总数达到8 从 -O(与-O1相同) -O0(不进行优化,如果未

有多少优化级别

我试过gcc-O1、gcc-O2、gcc-O3和gcc-O4

如果我使用一个非常大的数字,它将不起作用

然而,我已经试过了

gcc -O100
它被编译了


有多少优化级别?

四(0-3):参见GCC 4.4.2。任何更高的值都只是-O3,但在某一点上,您将超出可变大小限制。

为了学究式的理解,您可以为gcc提供8种不同的有效-O选项,尽管有些选项的含义相同

该答案的原始版本说明有7个选项。此后,GCC增加了
-Og
,使总数达到8

  • -O
    (与
    -O1
    相同)
  • -O0
    (不进行优化,如果未指定优化级别,则为默认值)
  • -O1
    (最低限度地优化)
  • -O2
    (优化更多)
  • -O3
    (进一步优化)
  • -Ofast
    (非常积极地进行优化,达到违反标准的程度)
  • -Og
    (优化调试体验。-Og启用不会干扰调试的优化。它应该是 标准编辑编译调试周期的优化级别选择,提供合理的优化级别 同时保持快速编译和良好的调试体验。)
  • -Os
    (针对大小进行优化。
    -Os
    启用通常不会增加代码大小的所有
    -O2
    优化。它还执行进一步的优化 旨在减少代码大小。
    -Os
    禁用以下优化标志:
    -falign函数-falign跳跃-falign循环-falign标签-freorder块-freorder块和分区-fprefetch循环数组-ftree向量循环版本
也可能有特定于平台的优化,正如@pauldoo所指出的,OS X有七个不同的级别:

  • -O0
    (默认):无优化

  • -O
    -O1
    (同样的事情):优化,但不要花费太多时间

  • -O2
    :更积极地优化

  • -O3
    :最积极地优化

  • -Ofast
    :相当于
    -O3-ffast数学
    <代码>-ffast math触发不符合标准的浮点优化。这允许编译器假装浮点数是无限精确的,并且浮点数上的代数遵循实数代数的标准规则。它还告诉编译器告诉硬件将非规范化刷新为零,并将非规范化视为零,至少在某些处理器上是这样,包括x86和x86-64。非规范化会在许多FPU上触发一条慢路径,因此将其视为零(这不会触发慢路径)可能是一个巨大的性能胜利

  • -Os
    :优化代码大小。由于更好的I-cache行为,在某些情况下,这实际上可以提高速度

  • -Og
    :优化,但不要干扰调试。这使调试版本的性能不会令人尴尬,并用于替换调试版本的
    -O0

还有一些其他选项不是由这些选项中的任何一个启用的,必须单独启用。也可以使用优化选项,但禁用此优化启用的特定标志


有关更多信息,请参阅GCC网站。

让我们来解释GCC 5.1的源代码。

我们将尝试了解
-O100
上发生了什么,因为手册页上不清楚

我们将得出结论:

  • 任何高于
    -O3
    INT_MAX
    的内容都与
    -O3
    相同,但这在将来很容易改变,因此不要依赖它
  • 如果输入的整数大于
    INT\u MAX
    ,GCC 5.1将运行未定义的行为
  • 参数只能有数字,否则将正常失败。特别是,这排除了像
    -O-1
关注子程序

首先要记住,GCC只是
cpp
as
cc1
collect2
的前端。一个快速的
/XXX--help
说明只有
收集2
cc1
才能获取
-O
,所以让我们重点关注它们

以及:

给出:

COLLECT_GCC_OPTIONS='-O100' '-v' '-mtune=generic' '-march=x86-64'
/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1 [[noise]] hello_world.c -O100 -o /tmp/ccetECB5.
因此
-O
被转发到
cc1
collect2

O共同点。选择

是中描述的特定于GCC的CLI选项描述格式,并由和转换为C

它包含以下有趣的行:

O
Common JoinedOrMissing Optimization
-O<number>  Set optimization level to <number>

Os
Common Optimization
Optimize for space rather than speed

Ofast
Common Optimization
Optimize for speed disregarding exact standards compliance

Og
Common Optimization
Optimize for debugging experience rather than speed or size
作为奖励,当我们在
\bO\n
中搜索
common.opt
时,我们注意到以下几行:

-optimize
Common Alias(O)
Variable
int optimize
这告诉我们,
--optimize
(双破折号,因为它在
.opt
文件上以破折号
-optimize
开头)是
-O
的未记录别名,可以用作
--optimize=3

使用OPT_O的位置

现在我们grep:

git grep -E '\bOPT_O\b'
这就指向了两个文件:

让我们首先跟踪
opts.c

选项c:默认选项\u优化

所有
opts.c
用法都发生在内部:
默认选项\u优化

我们grep backtrack查看是谁调用此函数,我们看到唯一的代码路径是:

  • main.c:main
  • toplev.c:toplev::main
  • opts global.c:decode\u opts
  • opts.c:默认选项优化
main.c
cc1
的入口点。好!

此功能的第一部分:

  • 调用integral\u参数
    git grep -E '\bOPT_O\b'
    
    struct gcc_options {
        int x_optimize;
        [...]
    }
    
    Variable
    int optimize
    
    struct gcc_options global_options;
    
    if ((unsigned int) opts->x_optimize > 255)
      opts->x_optimize = 255;
    
    # All of the optimization switches gathered together so they can be saved and restored.
    # This will allow attribute((cold)) to turn on space optimization.
    
    struct GTY(()) cl_optimization
    {
      unsigned char x_optimize;
    
    switch (default_opt->levels)
      {
    
      [...]
    
      case OPT_LEVELS_1_PLUS:
        enabled = (level >= 1);
        break;
    
      [...]
    
      case OPT_LEVELS_3_PLUS:
        enabled = (level >= 3);
        break;
    
    enum opt_levels
    {
      OPT_LEVELS_NONE, /* No levels (mark end of array).  */
      OPT_LEVELS_ALL, /* All levels (used by targets to disable options
                         enabled in target-independent code).  */
      OPT_LEVELS_0_ONLY, /* -O0 only.  */
      OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og.  */
      OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og.  */
      OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og.  */
      OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os.  */
      OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og.  */
      OPT_LEVELS_3_PLUS, /* -O3 and above.  */
      OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os.  */
      OPT_LEVELS_SIZE, /* -Os only.  */
      OPT_LEVELS_FAST /* -Ofast only.  */
    };
    
    static const struct default_options default_options_table[] = {
        /* -O1 optimizations.  */
        { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
        [...]
    
        /* -O3 optimizations.  */
        { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
        [...]
    }
    
    /* Wrapper to call lto.  Used by collect2 and the linker plugin.