インテル® C++ コンパイラー 19.0 デベロッパー・ガイドおよびリファレンス
プロシージャー間の最適化 (IPO) はマルチステップの自動処理で、コンパイラーがコードを解析してどの最適化が有効であるかを判断できるようにします。
コンパイラーは、次のような最適化を適用します。
アドレスの解析
配列次元のパディング
エイリアス解析
配列の自動転置
メモリープールの自動生成
C++ クラス階層解析
共通ブロック変数の統合
共通ブロックの分割
定数の伝播
不要な呼び出しの検出
不要な仮引数の排除
不要な関数の排除
仮引数のアライメント解析
前方代入
間接呼び出し変換
インライン展開
mod/ref 解析
不要な呼び出しの部分的に排除
レジスターに引数を渡して呼び出しとレジスターの使用を最適化
ポインター解析
ルーチンのキー属性の伝播
専用化
スタックフレームのアライメント
構造体分割とフィールドの並べ替え
シンボル・テーブル・データの促進
未参照変数の削除
プログラム全体の解析
IPO は単一ファイルのコンパイルと複数ファイルのコンパイルの 2 つのコンパイルモデルをサポートしています。
単一ファイルのコンパイルでは [Q]ip コンパイラー・オプションを使用し、コンパイルする各ソースファイルに対して 1 つのオブジェクト・ファイルを生成します。単一ファイルのコンパイル中に、コンパイラーは現在のソースファイル内で定義されているプロシージャーへの呼び出しをインライン展開します。
コンパイラーは、デフォルトの最適化レベル O2 でいくつかの単一ファイルの IPO を行います。また、O1 最適化レベルで、インラインプラグマまたは属性 (GNU* C および C++) が表記されている関数、およびクラスの宣言に関数本体が含まれている C++ クラスメンバー関数などのインライン展開を行うこともあります。
複数ファイルのコンパイルでは [Q]ipo オプションを使用し、通常のオブジェクト・ファイルではなく 1 つまたは複数の擬似オブジェクト・ファイルを生成します。(擬似オブジェクト・ファイルについての詳細は、下の「コンパイル」セクションを参照してください。) また、コンパイラーは、プログラムを構成する個々のソースファイルからの情報を収集します。コンパイラーはこの情報を使用して、異なるソースファイルの関数とプロシージャーを最適化します。
インライン展開およびその他の最適化は、プロファイル情報によって向上します。プロファイル情報を用いた IPO で最適化を実行する方法は、「アプリケーションのプロファイル」を参照してください。
IPO を使用して各ソースファイルがコンパイルされるたびに、コンパイラーはソースコードの中間表現 (IR) を擬似オブジェクト・ファイルに格納します。擬似オブジェクト・ファイルには、通常のオブジェクト・ファイルの代わりに IR が含まれます。擬似オブジェクト・ファイルは、通常のオブジェクト・ファイルのサイズよりも 10 倍以上の大きさになることがあります。
IPO コンパイルフェーズでは、擬似オブジェクト・ファイルのみが表示されます。
[Q]ipo コンパイラー・オプションを使用してリンクすると、コンパイラーはリンカーの直前に起動されます。コンパイラーは、すべての擬似オブジェクト・ファイルを対象に IPO を実行します。インテル® コンパイラーまたはインテルのリンクツールを使用して、擬似オブジェクトをリンクする必要があります。IPO によるリンク中に、インテル® コンパイラーと他のリンクツールは、擬似オブジェクト・ファイルをコンパイルし、ユーザー・プラットフォームで提供されるオブジェクト・ファイル・リンカーを呼び出します。
-ffat-lto-objects コンパイラー・オプションによるリンク時の最適化は GCC との互換性のために提供されています。IPO コンパイル中に -ffat-lto-objects オプションを指定すると、実際のオブジェクトと破棄可能な中間言語セクションの両方を含む、リンク時の最適化 (LTO) 用の FAT オブジェクトを生成できます。これにより、リンク時の最適化 (LTO) によるリンクと通常のリンクの両方が可能になります。
-fno-fat-lto-objects オプションを指定すると、破棄可能な中間言語セクションのみを含む (実際のオブジェクトを含まない) リンク時の最適化 (LTO) 用のオブジェクトを生成できます。これらのファイルは、生成された形式でアーカイブに追加されます。このオプションを使用することで、コンパイル時間が向上し、オブジェクトに必要な領域を減らせる可能性があります。
xild の代わりに ld でオブジェクトをリンクしたり、xiar の代わりに ar でアーカイブを作成すると、FAT リンク時の最適化中に生成されたオブジェクトは適切にリンクされ、アーカイブが作成されます。ただし、この場合、ファイル間の最適化は行われません。追加のオブジェクトはサイズとコンパイル時間を増加させるため、IPO 擬似オブジェクト・ファイルを xild でリンクし、xiar でアーカイブする場合は -fno-fat-lto-objects コンパイラー・オプションを使用するほうが良いでしょう。
コンパイラーは、プログラム全体の条件が満たされると適用できる IPO 最適化、または効率性が大幅に向上する多くの IPO 最適化をサポートしています。
解析処理中、コンパイラーは擬似ファイル、オブジェクト・ファイル、ライブラリー・ファイルにあるすべての中間表現 (IR) を読み取り、すべての参照が解決されているか、またはシンボルが擬似オブジェクト・ファイルに定義されているかどうかを判断します。データと関数の両方の擬似オブジェクト・ファイルにある IR に含まれているシンボルは、プログラム全体の解析の結果に基づいた操作を行う候補です。
プログラム全体の解析には、オブジェクト・リーダー・メソッドとテーブルメソッドの 2 種類があります。いずれかの解析でプログラム全体の条件が満たされいてると判断された場合には、ほとんどの最適化が適用できます。ただし、最適化によっては、オブジェクト・リーダー・メソッドにより生成される結果が必要なものと、テーブルメソッドにより生成された結果が必要なものとがあります。
オブジェクト・リーダー・メソッド
オブジェクト・リーダー・メソッドでは、オブジェクト・リーダーによりネイティブリンカーの動作をエミュレートし、アプリケーションのシンボルを解決しようとします。すべてのシンボルが解決されると、プログラム全体の条件が満たされたことになります。このプログラム全体の解析では、プログラム全体の条件が検出される可能性が高くなります。
テーブルメソッド
テーブルメソッドでは、コンパイラーが擬似オブジェクト・ファイルを解析して、コールグラフを作成します。
コンパイラーには libc などのすべての重要な言語固有のライブラリー関数についての詳細なテーブルが含まれています。この 2 番目のメソッドでは、コンパイラーはアプリケーションのコールグラフを作成します。それから、コンパイラーは関数テーブルとアプリケーションのコールグラフを比較します。コールグラフ中の未解決の各シンボルについて、コンパイラーは、コンパイラー・テーブルにある未解決の関数を検索することで、そのような呼び出しを解決しようとします。コンパイラーが関数を解決できた場合にプログラム全体の条件が整います。