コンパイラ最適化
1つのループを複数の同じインデックス範囲のループに分割する(各ループにはオリジナルのループ内の処理の一部が入る)。ループ内で参照されるデータとループ内のコードの両面で参照の局所性を高める。
ポインタのある言語では、変数をポインタを通じて参照・操作する可能性があるため、最適化が難しい。このため、どのポインタがどの変数のエイリアス(別名)であるかを識別することで無関係のポインタを無視する最適化を行う。
線形計画に基づいて計算を再配置することで参照の局所性を向上させたり、並列性を引き出したりする。
Javaのような言語では、配列にアクセスする際に常に指定されたインデックスが、配列の範囲内に収まっているかどうか実行時にチェックが行われる。このチェックは、科学技術計算のような性能が重視されるアプリケーションでは性能を悪化させてしまう。境界検査除去は、チェックを安全な局面で除去するものである。例えば、ループ変数が配列のインデックスとして使われている場合、ほとんどの境界検査は除去できる。
行列の乗算などはメモリアクセスが多く、キャッシュヒット率も悪い。入れ子ループ最適化では、ループ交換などの技法を使ってキャッシュヒット率を向上させる。
一部のCPUは複数のALUやFPUを備えており、複数の命令を同時に実行できる。同時に実行できる命令の種類には制限があることもあり、各ユニットが実行できる命令の種類も制限がある。これらにはパイプライン衝突と同様の問題が存在する。
コンパイラはこのような場合も命令をうまく配置して、各機能ユニットがなるべく常に動作するようにスケジュールできる。
パイプラインは、CPUを機能分割して工場の生産ラインのように並べたものと言える。基本的なパイプラインのステージは、命令の読み込み、命令のデコード、演算、メモリアクセス、レジスタへの格納である。これにより、CPUの各部が異なる命令の異なる処理をすることが可能となる。すなわち、ある命令の演算を行っているとき、同時に別の命令をデコード可能である。パイプラインのあるステージにある命令がもっと先のステージにある未完了の命令の結果を必要とするとき、パイプラインハザードが発生する。ハザードはパイプラインの停止(ストール)を招き、ハザードが解決されるまでCPUは処理を遅延させる。
コンパイラは依存関係を持つ命令群を実行結果に影響しないよう注意しながら再配置を行い、ストールが起こりにくくする。
ループ変数の値の変化する順序を反転させる(例えば、0 から 10 だったものを 10 から 0 にする)。これは微妙な最適化であり、依存関係解析を省く効果があったり、他の最適化が可能になるなどの効果が期待できる。
各文を1つの定義先、2つの参照先の3つ組で表現する形式。複雑な式が簡略化され、命令レベルの表現に近くなるという利点がある。
特定のマシン上で動作することが決まっているソフトウェアでは、そのマシン向けに最適化できる。例えば、並列コンピュータやベクトル計算機向けの並列化コンパイラなどがある。