11

GCCを使用してCプログラムをコンパイルする場合のデフォルトの最適化レベルは-O0です。 GCCのドキュメントに従ってすべての最適化を無効にします。例えば :しかしGCCのすべての最適化オプションを無効にする

gcc -O0 test.c 

、-O0はすべての最適化を本当にオフにされたかどうかを確認します。私はこのコマンドを実行しました:

gcc -Q -O0 --help=optimizers 

ここで私はちょっと驚きました。私は約50のオプションを有効にしました。 はその後、私はこれを使用してgccのために渡されるデフォルトの引数をチェックする:

gcc -v 

私はこれだ:だから私の結論は私がプログラムに提供-O0フラグが何かによってoveridedされなかったということです

Using built-in specs. 
COLLECT_GCC=gcc 
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper 
Target: x86_64-linux-gnu 
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-  
2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --  
enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr -- 
program-suffix=-4.8 --enable-shared --enable-linker-build-id -- 
libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with- 
gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with- 
sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx- 
time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin -- 
with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk- 
cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable- 
java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with- 
jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch- 
directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc- 
gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 -- 
with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release 
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu 

Thread model: posix 

gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) 

をelse。

実際、最適化オプションのランダムシーケンスを生成し、生成されたシーケンスをデフォルトレベルO0-3と比較するツールを最初から実装しようとしています。ちょうど "acovea"のように。そのため、生成されたシーケンスをゼロ最適化レベル(O0にする必要があります)と比較したいのですが

-O0では50個のオプションがデフォルトで有効になっています。

O0 + O0でデフォルトの最適化を無効にしてコンパイルすることをお勧めします。-fno-OPTIMIZATION_NAMEを50回使用してください。どう思いますか?

+1

'-O0'で有効になっているオプションのほとんどは*最適化オプションではありません(しかし、いくつかあります)。 –

+1

@ KonradRudolphこの現象は、私を強く悩ます。いくつかのあいまいな振る舞いをデバッグするとき、私はすべての最適化をオフにします。 :) Sambaのコンパイラは、聞いてくれません。:) –

+0

@MartinJames -fnoの代わりに-fno(GCCの場合)を書くことによって、すべての-fフラグを手動で無効にすることができます。それは動作しますが、時間がかかり実用的ではありません – staticx

答えて

5

まあ

gcc -O0 `gcc -Q -O0 --help=optimizers 2>&1 | perl -ane 'if ($F[1] =~/enabled/) {$F[0] =~ s/^\s*-f/-fno-/g;push @o,$F[0];}} END {print join(" ", @o)'` your args here 

は(不潔)のすべてのオプションをオフにします。

さらに深刻なことに、すべての最適化状態をカバーしている場合は、どうにかする必要がある最適化フラグのリストを作成し、それぞれ-fmyflagまたは-fno-myflagで明示的にオンまたはオフにします。これは本質的にあなたの2番目の質問に答えます。

しかし、すべて-Oレベルの最適化をオフにして遊んだりする価値はないと考えるかもしれません。「それはhttps://github.com/gcc-mirror/gcc/blob/master/gcc/toplev.cが何をするかだから」は、それはそれは「広すぎる」の間のどこかだ、というようなものだ(つまり、あなたがそれを書いた人は誰でも依頼する必要があります)と理由については

文書には、-O0が最適化を無効にしているとは言わないことに注意してください。 (man pageから):

-O0コンパイル時間を短縮し、デバッグで期待される結果が得られるようにします。これがデフォルトです。

コンパイル時間を増やさずにデバッグに影響を与えない最適化があるかもしれませんが、これらは残されます。

だから私はO0でコンパイルすると、何の最適化が適用されないことを意味しないことを言わせて:

+0

はい、O0レベル内でいくつかのオプションが有効になっている理由を理解する必要があります – staticx

+0

これはhttps://github.com/gcc-mirror/gcc/blobなので、 /master/gcc/toplev.cは '* – abligh

+0

ポインタのためにありがとうございます。プログラムをコンパイルするときにデフォルトでいくつかの最適化オプションが有効になっている場合、GCCの人々はO0に最適化が全くないと言っているのです。これはちょっと変わっちゃった – staticx

3

私の質問に答えるためには、私はいくつかの結論と仮定してきました。上記の@ablighのように、コンパイル時間を短縮し、デバッグを改善するオプションが有効になります。

つまり、O0はコンパイルレベルを最適化しています。生成されたバイナリは、デバッグプロセスを容易にするために最適化されていません。

私は例を与える:このオプションは、ループオプティマイザに指示します

:このオプションは、O0レベルGCCのドキュメントで

-faggressive-ループの最適化

で有効になっています言語の制約を使用してループの反復回数の範囲を導出する。これは、ループコードが、例えば、符号付き整数オーバーフローまたはアウトオブバウンド配列アクセスを引き起こすことによって、未定義の動作を呼び出さないことを前提としています。ループの繰返し回数の範囲は、ループのアンローリングおよびピーリングおよびループ出口テストの最適化を導くために使用されます。 このオプションは、デフォルトで有効になっています。

GCC 4.8.xでは、デフォルトで約50のオプションが有効になっています。

+0

'-O0'で有効になっていますか?私は、「デフォルトで有効になっている」と解釈するのは、「デフォルトでは無効にならない」という意味ですが、それはすべての最適化レベルで使用されていることを意味するものではありません。私はそれが有効になったときに '-O2'または' -O3'でのみ使用されると思います。 –

+0

gcc -Q -O0を使って確認できます--help = optimizers – staticx

+0

OK、それは私に興味をそそられた監視の –

12

Stricto sensuでは、GCCコンパイラの中間エンドは最適化パスのシーケンス(実際にネストされたツリー、コンパイル時に動的に変更される)で作られているため、GCCが最適化を行わなかった場合、 。

GCCへの入力言語は非常に豊富です(while,forなど)がありますが、中間のGimple言語ははるかに貧弱です(特にGimple/SSA)ので変換を適用する必要がありますソースASTからジンプルに行く。これらの変換はほぼ定義通りに最適化パスです。

answerthis(SVG画像)の画像も参照してください。hereを参照してください。

あなたは、いくつかの実行可能ファイルを生成するために必要ではない(例えば-O1などが提供する...)任意の追加の最適化を無効にするよう-O0を理解する必要があります。

関連する問題