コンパイラーがデフォルトで実行するのは、ローカルでの簡単な最適化 (定数のフォールディング、ローカルでの共通部分式の除去など) のみですが、完全なデバッグもサポートされています。プログラムは、さまざまな最適化レベルを指定することにより最適化できますが、最適化によってアプリケーションのパフォーマンスが向上すると、逆にプログラム・サイズやデバッグ・サポートは大きくなります。次の表に、指定できるオプションをまとめてあります。また、それぞれの最適化レベルで使用される手法の詳細説明は、後述します。
表 8. 最適化レベル
オプション
| 振る舞い
|
-O、-O2、-qoptimize、または -qoptimize=2
| 低レベルの包括的最適化。部分的なデバッグ・サポート。
|
-O3 または -qoptimize=3
| より広範囲にわたる最適化。精度とのトレードオフあり。
|
-O4 または -qoptimize=4
| プロシージャー間の最適化。ループの最適化。自動マシン調整。
|
-O5 または -qoptimize=5
|
最適化レベル 2 では、コンパイラーが適用する最適化手法は保守的であり、プログラムの正確さに影響を及ぼさないものとされます。最適化レベル 2 では、次の手法が使用されます。
最適化レベル 3 以上では、コンパイラーはよりアグレッシブになり、変更によって別の結果が生じるリスクを冒しても、プログラム・セマンティクスを変更してパフォーマンスの向上を図ります。次に、いくつか例を挙げます。
- 場合によっては、X*Y*Z を、(X*Y)*Z ではなく X*(Y*Z) として計算します。こうすると、丸めのために結果が異なる場合があります。
- 場合によっては、負のゼロ値の符号を省略します。こうすると、その値に無限大を掛けた場合に結果が異なる可能性があります。
最適化レベル 2 および 3 の最大活用には、このリスクを少なくするための提案があります。
最適化レベル 3 では、最適化レベル 2 で使用されるすべての手法に加えて、次のような手法が使用されます。
- より深いループをアンロールし、ループ・スケジューリングを改善します。
- 最適化の範囲を拡張します。
- 効果の微小な最適化や、一部の条件下でのみ有用な最適化など、すべてのプログラムで役立つとは限らない最適化も実行します。
- コンパイル時間やスペースをかなり消費する最適化も実行します。
- 一部の浮動小数点計算の順序を変更します。これによって精度差が生じたり、または浮動小数点関連の例外の発生に影響を及ぼす可能性があります (-qnostrict オプションによるコンパイルに相当)。
- 暗黙のメモリー使用量制限を除去します (-qmaxmem=-1 オプションによるコンパイルに相当)。
- 自動インライン化を拡張します。
- 構造体のコピーを介して定数および値を伝搬します。
- 可能であれば、他の最適化のあとで「address taken」属性を除去します。
- 隣接する集合体メンバーでのロード、保管、その他のオペレーションをグループ化します。その際、場合によっては、VMX ベクトル登録オペレーションを使用します。
最適化レベル 4 および 5 では、最適化レベル 2 および 3 で使用されるすべての手法に加えて、次のような手法が使用されます。
- プロシージャー間分析。リンク時に最適化プログラムを呼び出して、複数のソース・ファイル間で最適化を実行します (-qipa オプションによるコンパイルに相当)。
- 高位変換。ループ・ネストと配列言語構造体の最適化処理を行います (-qhot オプションによるコンパイルに相当)。
- ハードウェア固有の最適化 (-qarch=auto、-qtune=auto、および -qcache=auto オプションによるコンパイルに相当)。
- 最適化レベル 5 では、さらに詳細なプロシージャー間分析 (-qipa=level=2 オプションによるコンパイルに相当)。レベル 2 IPA では、高位の変換 (-qhot によるコンパイルに相当) は、プログラム全体の情報が収集された後は、リンク時まで遅らせられます。
ここでは、最適化レベル 2 および 3 を使用する際の、推奨される方法について説明します。
- 可能であれば、まず最適化しないでコードをテストおよびデバッグしてから、
-O2 を使用します。
- ご使用のコードが言語標準に準拠していることを確認します。
-
C コードでは、ポインターの使用が次の制約事項に従っていることを確認してください。つまり、汎用ポインターは char* または void* でなければなりません。また、すべての共用変数および共用変数に対するポインターは、volatile でマークされている必要があります。
-
C では、プログラムが独自の関数をライブラリー関数と同じ名前で定義しているのでない限り、
-qlibansi コンパイラー・オプションを使用します。
- コードのできるだけ多くの部分を、-O2 でコンパイルします。
- -O2 を使用して問題が発生する場合は、最適化を無効にする代わりに、
-qalias=noansi を使用することを検討してください。
- 次に、-O3 をできるだけ多くのコードに対して使用します。
- 問題が発生したり、パフォーマンスが低下したりする場合は、必要に応じて、
-O3 と一緒に -qstrict または -qcompact を使用することを検討してください。
- -O3 の使用時の問題が改善されない場合は、ファイルの一部に対しては -O2 に切り替えますが、
-qmaxmem=-1、-qnostrict のいずれか、または両方を使用することを検討してください。
