どのように多くのGCCの最適化のレベルがありますか?
gcc -O1、gcc -O2、gcc -O3、gcc -O4を試しました
非常に大きな数を使用すると、機能しません。
しかし、私は試しました
gcc -O100
そしてそれはコンパイルされました。
最適化レベルはいくつありますか?
-fomit-stack-pointer
生成されたコードを変更します。
どのように多くのGCCの最適化のレベルがありますか?
gcc -O1、gcc -O2、gcc -O3、gcc -O4を試しました
非常に大きな数を使用すると、機能しません。
しかし、私は試しました
gcc -O100
そしてそれはコンパイルされました。
最適化レベルはいくつありますか?
-fomit-stack-pointer
生成されたコードを変更します。
回答:
わかりやすくするために、gccに指定できる有効な-Oオプションは8つありますが、同じことを意味するものもあります。
この回答の元のバージョンでは、7つのオプションがあると述べていました。その後、GCCは-Og
合計を8にするために追加しました
-O
(と同じ-O1
)-O0
(最適化を行わない、最適化レベルが指定されていない場合のデフォルト)-O1
(最小限に最適化)-O2
(さらに最適化)-O3
(さらに最適化)-Ofast
(非常に積極的に最適化して、標準準拠に違反するまで)-Og
(デバッグエクスペリエンスを最適化します。-Ogは、デバッグを妨げない最適化を有効にします。これは、標準の編集、コンパイル、デバッグサイクルに最適な最適化レベルである必要があり、高速コンパイルと優れたデバッグエクスペリエンスを維持しながら、妥当なレベルの最適化を提供します。 )-Os
(サイズの最適化は、-Os
すべての可能-O2
典型的には、コードサイズを増加させない最適化をまた、コードサイズを低減するように設計されたさらなる最適化を行う。。
-Os
以下の最適化フラグを無効にします。-falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version
)@pauldooが指摘するように、OS Xにはプラットフォーム固有の最適化もあるかもしれません -Oz
-Oz
「よりも、より積極的に大きさのために最適化され、設定-Os
:」developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/...
-Og
、これはデバッグに干渉しないすべての最適化オプションです
マニュアルページでは明確ではないので、GCC 5.1のソースコードを解釈して何が起こるか見てみましょう-O100
。
次のように結論付けます。
-O3
まではINT_MAX
同じである-O3
が、それは簡単に、将来的に変更される可能性がそれに依存しないでください。INT_MAX
。-O-1
サブプログラムに焦点を当てる
まず、GCCがためだけのフロントエンドであることを覚えておいてくださいcpp
、as
、cc1
、collect2
。簡単に./XXX --help
言うと、それだけcollect2
をcc1
取る-O
ので、それらに焦点を当てましょう。
そして:
gcc -v -O100 main.c |& grep 100
与える:
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
。
common.optのO
common.optはGCC固有のCLIオプションの説明形式で、内部のドキュメントに記載されており、opth-gen.awkおよびoptc-gen.awkによって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
すべてのO
オプションを指定します。どのように注意し-O<n>
、他のとは別の家族の中でOs
、Ofast
とOg
。
ビルドすると、以下options.h
を含むファイルが生成されます。
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
我々はgrepをしている間、ボーナスとして、\bO\n
内部のcommon.opt
私たちは、行に気づきます:
-optimize
Common Alias(O)
そのことを私たちに教えて--optimize
(ダブルダッシュ、それはダッシュで始まるので、-optimize
上の.opt
ファイル)のために文書化されていないエイリアスである-O
として使用することができます--optimize=3
!
OPT_Oが使用される場所
今私たちはグレップ:
git grep -E '\bOPT_O\b'
これは2つのファイルを示しています。
まずは追跡してみましょう opts.c
opts.c:default_options_optimization
すべてのopts.c
使用は内部で発生します:default_options_optimization
。
バックトラックをgrepして、誰がこの関数を呼び出しているかを確認します。コードパスは次のとおりです。
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
とmain.c
のエントリポイントですcc1
。良い!
この関数の最初の部分:
integral_argument
を呼び出して入力引数を解析しますatoi
OPT_O
opts->x_optimize
ところopts
ですstruct gcc_opts
。構造体gcc_opts
無駄にgreppingした後、これstruct
も次の場所で生成されていることがわかりoptions.h
ます。
struct gcc_options {
int x_optimize;
[...]
}
どこx_optimize
の行から来る:
Variable
int optimize
に存在しcommon.opt
、それoptions.c
:
struct gcc_options global_options;
したがって、これが構成グローバル状態全体を含むものであると推測します。 int x_optimize
あり、最適化値ます。
255は内部最大値です
in opts.c:integral_argument
ではatoi
、入力引数に適用されるためINT_MAX
、上限も同様です。そして、もっと大きなものを置くと、GCCはCの未定義の動作を実行しているようです。痛い?
integral_argument
またatoi
、いずれかの文字が数字でない場合は、引数を薄くラップして拒否します。したがって、負の値は正常に失敗します。
に戻るとopts.c:default_options_optimization
、次の行が表示されています。
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
最適化レベルがに切り捨てられるようにし255
ます。読んでいる間にopth-gen.awk
私は出くわしました:
# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.
そして生成されたoptions.h
:
struct GTY(()) cl_optimization
{
unsigned char x_optimize;
切り捨ての理由を説明します。オプションはにも転送する必要がcl_optimization
あります。char
スペースを節約するためにに。つまり、255は実際には内部最大値です。
opts.c:maybe_default_options
に戻るとopts.c:default_options_optimization
、maybe_default_options
興味深い音に出会います。それを入力してからmaybe_default_option
、大きなスイッチに到達します。
switch (default_opt->levels)
{
[...]
case OPT_LEVELS_1_PLUS:
enabled = (level >= 1);
break;
[...]
case OPT_LEVELS_3_PLUS:
enabled = (level >= 3);
break;
>= 4
チェックはありません。これは、それ3
が可能な限り大きいことを示しています。
次に、OPT_LEVELS_3_PLUS
in の定義を検索しますcommon-target.h
。
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. */
};
ハ!これは、レベルが3つしかないことを示す強力な指標です。
opts.c:default_options_table
opt_levels
我々はgrepすることを、とても興味深いですOPT_LEVELS_3_PLUS
、とに遭遇opts.c:default_options_table
:
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 },
[...]
}
そのため-On
、ドキュメントに記載されている特定の最適化マッピングがエンコードされます。いいね!
x_optimizeをこれ以上使用しないようにします
の主な用途は、manページに記載されているx_optimize
ような他の特定の最適化オプションを設定することでした-fdefer_pop
。これ以上ありますか?
私たちはgrep
、さらにいくつかを見つけます。数は少なく、手動で調べると、すべての使用法が最大でaしか行わないことがわかりx_optimize >= 3
ます。そのため、結論は成り立ちます。
lto-wrapper.c
今、私たちは第二の発生のために行くOPT_O
にありました、lto-wrapper.c
。
LTOは、リンクタイムの最適化を意味します。これは、名前が示すように、-O
オプションが必要であり、リンクされますcollec2
(基本的にはリンカーです)。
実際には、の最初の行はlto-wrapper.c
言う:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
このファイルでは、OPT_O
オカレンスはO
それを転送するためにの値を正規化するだけのようですので、問題ありません。
7つの異なるレベル:
-O0
(デフォルト):最適化なし。
-O
または-O1
(同じこと):最適化しますが、あまり時間をかけないでください。
-O2
:より積極的に最適化する
-O3
:最も積極的に最適化する
-Ofast
:に相当し-O3 -ffast-math
ます。 -ffast-math
非標準に準拠した浮動小数点最適化をトリガーします。これにより、コンパイラーは、浮動小数点数が無限に正確であり、それらの代数が実数代数の標準規則に従っているように見せかけることができます。また、少なくともx86とx86-64を含む一部のプロセッサでは、ハードウェアにデノーマルをゼロにフラッシュし、デノーマルをゼロとして扱うように指示します。デノーマルは多くのFPUで低速パスをトリガーするため、それらをゼロとして処理すると(低速パスをトリガーしません)、パフォーマンスが大幅に向上します。
-Os
:コードサイズを最適化します。これにより、Iキャッシュの動作が改善されるため、実際には速度が向上する場合があります。
-Og
:最適化しますが、デバッグを妨げません。これにより、デバッグビルドで非の打ちどころのないパフォーマンスが可能になり、デバッグビルドに置き換わるもの-O0
です。
これらのいずれによっても有効にされていないオプションが他にもあり、個別に有効にする必要があります。最適化オプションを使用することもできますが、この最適化によって有効にされた特定のフラグを無効にします。
詳細については、GCC Webサイトを参照してください。
-O100
コンパイルするのでしょうか?
4(0-3):GCC 4.4.2 マニュアルを参照してください。それ以上のものは-O3だけですが、ある時点で可変サイズ制限をオーバーフローします。
man gcc
のCygwin(12000本の奇数ライン)上のあなたがのために検索することができます-O
と答え状態下のすべてを見つけるし、その後いくつかの。