コンパイラ最適化
1つのループを複数に分割するが、各ループの中身は同じで、ループ変数の範囲が異なるようにする。例えば、一般にループの1回目の実行では各種処理が余分に必要となっている場合がある。これを1回目だけ分割してみると、その後のループでは各種最適化が可能となる場合がある。
拡張命令(MMXやSSE等)を使う機械語を生成する。代わりに、それらに対応していないCPU上では動作しなくなる。
仮想的な機械の命令。
ループの中身のコードを複数回配置してループ条件のチェック回数を減らしたり、分岐回数を減らすことによってオーバーヘッドを低減させる。ループを完全に展開すればオーバーヘッドはゼロになるが、コンパイル時にループ回数が明確になっていなければならない。
プロシージャ間最適化はプログラム全体を対象とするもので、プロシージャの境界やファイルの境界を越えた最適化である。プロシージャ間で関係する部分に働き、局所的な最適化と大域的な最適化の協調によって行われる。主なプロシージャ間最適化としては、インライン展開、プロシージャ間デッドコード削除、プロシージャ間定数伝播、プロシージャ再配置などがある。通常、最適化の前にプロシージャ間解析が必要であり、プロシージャ間エイリアス解析、配列アクセス解析、コールグラフ構築などがある。
プロシージャ間最適化は最近の 商用コンパイラ(SGI、インテル、マイクロソフト、サン・マイクロシステムズ)にはほとんど備わっている。GCCには長い間プロシージャ間最適化がないことが弱点とされていた。しかし、現在ではプロシージャ間最適化を実装している。その他のオープンソースのコンパイラでプロシージャ間最適化を備えたものとして Open64 がある。こちらは研究用や商用にも利用されている。
プロシージャ間最適化(およびそのための解析)には時間とメモリを要するため、デフォルトでは実施しない設定になっているコンパイラが多い。ユーザーは明示的にオプションを指定して最適化することを指示しなければならない。
データフロー最適化はデータフロー解析に基づいて行われ、あるデータの特性が制御フローグラフ内の制御エッジでどのように伝播されるかによるもの。以下のような技法がある。
Global Value Numbering)
プログラムの値グラフを作成して冗長性を除去し、等価な式で計算される値を特定する。大域値番号付けは共通式削除ではできない冗長性の除去が可能である。逆に共通式削除でしかできない冗長性の除去もある。
インライン展開やループ展開などの手法はコードのサイズを増大させ、参照の局所性を損なう。頻繁に実行されるコードの塊がキャッシュに収まらなくなると、性能は劇的に低下する。フルアソシアティブでないキャッシュではキャッシュ上での衝突が発生しやすい。
条件文のthen部とelse部に同じ式がある場合、その計算を条件式の外で1回だけ行うようにする。同様に、定数の変数への代入のような式がループ内にある場合、ループ内で何度実施しても効果は同じであるため、それをループの外にくくり出すことができる(ループ不変量コード移動)。全体冗長性除去(Total Redundancy Elimination)。より強力な最適化として部分冗長性除去 (Partial Redundancy Elimination) がある。