web-dev-qa-db-ja.com

リンク時最適化(LTO)を使用しない理由はありますか?

GCC、MSVC、LLVM、およびおそらく他のツールチェーンは、コンパイル時の呼び出しの最適化を可能にするリンク時(プログラム全体)最適化をサポートしています。

実動ソフトウェアのコンパイル時にこのオプションを有効にしない理由はありますか?

46
Honza

"プロダクションソフトウェア"とは、顧客に出荷する/プロダクションに入るソフトウェアを意味すると想定しています。 なぜコンパイラ最適化を常に使用しないのか?Mankarse によって指摘される)の答えは、コードをデバッグしたい状況にほとんど当てはまります(したがって、ソフトウェアはまだ開発段階-本番ではありません)。

私が考えることができる唯一の良い、正当な理由は、リンク時間の最適化mayが微妙なバグを導入することです。 リンク時間のカーネルの最適化を参照) 。出荷しようとしているソフトウェアの正確性をチェックする適切なテストがあると仮定すると、デフォルトでLTOを使用しない理由はわかりません。 (LTOは時間とともに成熟しているため、これらの微妙なバグがますます少なくなることを期待しましょう。)

27
Ali

この最近の質問 は、LTOが望ましくない効果をもたらす可能性のある別の可能性のある(しかしかなり具体的な)ケースを発生させます:問題のコードがタイミングのために装備されており、相対的なインストルメントされたステートメントとインストルメントステートメントの順序付けを行うと、LTOは必要な順序付けを破棄する可能性が高くなります。

具体的だと言った。

9
Jeremy

よく書かれたコードを持っている場合、それは有利なだけです。コンパイラ/リンカーのバグに遭遇する可能性がありますが、これはあらゆるタイプの最適化に当てはまりますが、これはまれです。

最大の欠点は、リンク時間が大幅に増加することです。

4
ericcurtin

リンク時最適化が間違ったコードに対して予期しない動作を引き起こす可能性がある1つのシナリオは次のとおりです。

別々のオブジェクトファイルにコンパイルする2つのソースファイルread.cclient.cがあるとします。ファイルread.cには、特定のメモリアドレスからの読み取り以外は何もしないread関数があります。ただし、このアドレスのコンテンツはvolatileとマークする必要がありますが、残念ながら忘れていました。 client.cから関数readが同じ関数から数回呼び出されます。 readはアドレスから1回の読み取りのみを実行し、read関数の境界を超えた最適化は行われないため、readは呼び出されると常にそれぞれのメモリ位置にアクセスします。したがって、readclient.cから呼び出されるたびに、client.cのコードは、まるでvolatileが使用されたかのように、アドレスから新たに読み取られた値を取得します。

現在、リンク時最適化では、read.cから呼び出された場合に、client.cからの小さな関数readがインライン化される可能性があります。 volatileがないため、コンパイラはコードが同じアドレスから数回読み取ることを認識し、メモリアクセスを最適化することができます。その結果、コードは異なる動作を開始します。

0
Dirk Herrmann

To this とは別に、

組み込みシステムの典型的な例を考えてみましょう。

void function1(void) { /*Do something*/} //located at address 0x1000 
void function2(void) { /*Do something*/} //located at address 0x1100
void function3(void) { /*Do something*/} //located at address 0x1200

定義済みのアドレス指定関数を使用すると、以下のような相対アドレスを介して呼び出すことができます。

 void (*ptr)(void) = function1;
 (ptr + 0x100)(); //expected to call function2
 (ptr + 0x200)();  //expected to call function3

LOTは予期しない動作を引き起こす可能性があります。

0
pmp