ソフトウェアパイプライン
ループの前後で実行する前処理・後処理について説明する前に、このコードが繰り返し部分について元のコードと同じ結果を得られるかを検証する。元のループで7度目の繰り返しを考える。パイプライン化されたループの最初の繰り返しでは、元のループでの7度目の繰り返しまでの命令を含んでいる。命令列は下記のようになる。
Iteration 1: A(7) B(6) C(5) D(3) E(2) F(1)
Iteration 2: A(8) B(7) C(6) D(4) E(3) F(2)
Iteration 3: A(9) B(8) C(7) D(5) E(4) F(3)
Iteration 4: A(10) B(9) C(8) D(6) E(5) F(4)
Iteration 5: A(11) B(10) C(9) D(7) E(6) F(5)
Iteration 6: A(12) B(11) C(10) D(8) E(7) F(6)
Iteration 7: A(13) B(12) C(11) D(9) E(8) F(7)
しかし、元のループとは異なり、パイプライン化されたものは、命令 C のボトルネックを回避できる。C(7) およびその結果に依存した D(7) の間には命令が12個あり、C(7) のレイテンシが無駄にならずに他の命令の実行に使用される。
前処理と後処理では、繰り返しの始めと終わりを処理する。下記が前処理として考えられるコードである。
各行がパイプライン化されたループにおける一回分の繰り返しに相当し、繰り返し自体のための命令は取り除かれている。後処理も同様である。
インテルの IA-64 はこのようなソフトウェアパイプラインの困難な点を念頭に置いて設計されたアーキテクチャの一例である。ソフトウェアパイプラインに関係するアーキテクチャ上のポイントの主要なものとして、以下のような点などがある。
"rotating" レジスタバンク —— ループ内で、命令は別のレジスタを指すレジスタ番号を用いてレジスタを参照することができる(最終的には最初に戻ることができる)。これによって、上記の例のようにレジスタの重複を避けるための命令列を追加する必要がなくなる。
"predicate" レジスタ —— predicateレジスタは、ループ内の比較命令によりセットされる。その値により後続するスロットの実行/否を制御することで、分岐を削除しパイプラインの乱れを抑制する(if 変換)。IA-64のpredicate レジスタは、その名前からしばしば分岐予測(branch prediction)と混同されるが、ARMアーキテクチャの条件付き実行命令と同様のコンセプトで、参照するpredicate レジスタの値によってスロットのオペレーションの実行/否を制御するものである。64本あるpredicate レジスタの1つpr0は常に真を返し、無条件実行のために使われる。