(19)【発行国】日本国特許庁(JP)
(12)【公報種別】特許公報(B2)
(11)【特許番号】
(24)【登録日】2024-03-26
(45)【発行日】2024-04-03
(54)【発明の名称】コンパイラプログラム、コンパイル方法、情報処理装置
(51)【国際特許分類】
G06F 8/41 20180101AFI20240327BHJP
G06F 17/16 20060101ALI20240327BHJP
【FI】
G06F8/41 130
G06F17/16 G
(21)【出願番号】P 2020100151
(22)【出願日】2020-06-09
【審査請求日】2023-03-09
(73)【特許権者】
【識別番号】000005223
【氏名又は名称】富士通株式会社
(74)【代理人】
【識別番号】100094525
【氏名又は名称】土井 健二
(74)【代理人】
【識別番号】100094514
【氏名又は名称】林 恒徳
(72)【発明者】
【氏名】渡辺 健介
(72)【発明者】
【氏名】原口 正寿
(72)【発明者】
【氏名】鎌塚 俊
(72)【発明者】
【氏名】谷村 恭伸
【審査官】円子 英紀
(56)【参考文献】
【文献】特開平03-150636(JP,A)
【文献】特表2017-509999(JP,A)
【文献】特開昭62-169272(JP,A)
(58)【調査した分野】(Int.Cl.,DB名)
G06F 8/41
G06F 17/16
(57)【特許請求の範囲】
【請求項1】
最適化対象プログラムについて最適化処理をコンピュータに実行させるコンパイラプログラムであって、
前記最適化対象プログラムは、配列変数のベクトルストア命令とベクトルロード命令を有するループを有し、
前記最適化処理は、
前記ループ内の前記ベクトルストア命令とベクトルロード命令を、ベクトル長を前記配列変数の配列サイズで除算して余りを切り上げた第1アンロール数または前記第1アンロール数より1つ少ない第2アンロール数だけアンローリングを行い、
前記アンローリングした複数のベクトルロード命令のうち先頭のベクトルストア命令より後ろのベクトルロード命令を、前記先頭のベクトルストア命令より前に移動させるスケジューリングを行う、コンパイラプログラム。
【請求項2】
前記ループは、前記配列変数の配列サイズが定数でベクトル長が定数で、前記ループの回転数(m)が前記配列サイズより小さく、前記ループの回転数と前記ベクトル長の比がアンパック可能な特定の比ではない、請求項1に記載のコンパイラプログラム。
【請求項3】
前記最適化対象プログラムの前記ループは、
前記ループの複数の回転ループの前の回転ループ内のベクトルストア命令と後の回転ループ内のベクトルロード命令のベクトル長の要素に対するメモリアドレスが重なるが、両命令がマスクに基づきアクセスする要素のメモリアドレスは重ならない二次ストアフェッチインターロックに該当する、請求項2に記載のコンパイラプログラム。
【請求項4】
前記ループが前記ベクトルロード命令の後に前記ベクトルストア命令を有する場合、
前記二次ストアフェッチインターロックは、
(1)前記ループの第1回転目のベクトルストア命令のベクトル長の要素に対するメモリアドレスと、前記第1回転目の次の第2回転目のベクトルロード命令のベクトル長の要素に対するメモリアドレスとが重なるが、(2)前記第1回転目のベクトルストア命令がマスクに基づきアクセスする要素のメモリアドレスと、前記第2回転目のベクトルロード命令がマスクに基づきアクセスする要素のメモリアドレスとが重ならない場合である、請求項3に記載のコンパイラプログラム。
【請求項5】
前記ループが前記ベクトルストア命令の後に前記ベクトルロード命令を有する場合、
前記二次ストアフェッチインターロックは、
(1)前記ループの第1回転目のベクトルストア命令のベクトル長の要素に対するメモリアドレスと、前記第1回転目のベクトルロード命令のベクトル長の要素に対するメモリアドレスとが重なるが、(2)前記第1回転目のベクトルストア命令がマスクに基づきアクセスする要素のメモリアドレスと、前記第1回転目のベクトルロード命令がマスクに基づきアクセスする要素のメモリアドレスとが重ならない場合である、請求項3に記載のコンパイラプログラム。
【請求項6】
前記ループが前記ベクトルロード命令の後に前記ベクトルストア命令を有する場合、アンロール数は前記第1アンロール数であり、
前記ループが前記ベクトルストア命令の後に前記ベクトルロード命令を有する場合、アンロール数は前記第2アンロール数である、請求項1に記載のコンパイラプログラム。
【請求項7】
前記最適化処理は、更に、
前記配列変数の配列サイズが変数でベクトル長が定数または不明の場合、
前記ループを、前記配列サイズと前記ベクトル長の取り得る組み合わせに基づいて算出される前記第1アンロール数または前記第2アンロール数の複数のケースそれぞれについて、前記ループ内の前記ベクトルストア命令とベクトルロード命令を有するケース別ループに変換し、
前記アンローリングは、
前記ケース別ループそれぞれにおいて、前記アンローリングを行う処理を有し、
前記スケジューリングは、
前記ケース別ループそれぞれについて、前記スケジューリングを行う処理を有する、請求項1に記載のコンパイラプログラム。
【請求項8】
最適化対象プログラムについて最適化処理を行うコンパイル方法であって、
前記最適化対象プログラムは、配列変数のベクトルストア命令とベクトルロード命令を有するループを有し、
前記最適化処理は、
前記ループ内の前記ベクトルストア命令とベクトルロード命令を、ベクトル長を前記配列変数の配列サイズで除算して余りを切り上げた第1アンロール数または前記第1アンロール数より1つ少ない第2アンロール数だけアンローリングを行い、
前記アンローリングした複数のベクトルロード命令のうち先頭のベクトルストア命令より後ろのベクトルロード命令を、前記先頭のベクトルストア命令より前に移動させるスケジューリングを行う、コンパイル方法。
【請求項9】
プロセッサと、
前記プロセッサがアクセスするメモリを有し、
前記プロセッサは、最適化対象プログラムについて最適化処理を実行し、
前記最適化対象プログラムは、配列変数のベクトルストア命令とベクトルロード命令を有するループを有し、
前記最適化処理は、
前記ループ内の前記ベクトルストア命令とベクトルロード命令を、ベクトル長を前記配列変数の配列サイズで除算して余りを切り上げた第1アンロール数または前記第1アンロール数より1つ少ない第2アンロール数だけアンローリングを行い、
前記アンローリングした複数のベクトルロード命令のうち先頭のベクトルストア命令より後ろのベクトルロード命令を、前記先頭のベクトルストア命令より前に移動させるスケジューリングを行う処理を有する、情報処理装置。
【発明の詳細な説明】
【技術分野】
【0001】
本発明は、コンパイラプログラム、コンパイル方法、情報処理装置に関する。
【背景技術】
【0002】
コンパイラは、Fortran(フォートラン)やC言語のような高水準言語のプログラムを、アセンブリコードまたはオブジェクトコード(機械語)に翻訳するプログラムである。コンパイラの主な機能は、ソースコードである高水準言語プログラムを解析する解析機能と、ソースコードから中間言語の中間コードを生成する機能と、その中間コードを最適化する機能と、最適化された中間コードをアセンブリコードまたはオブジェクトコードに変換するコード生成機能などである。最適化機能では、例えば、複数のスカラー命令をベクトル命令(またはSIMD命令、Single Instruction Multiple Data、以下ベクトル命令と称する。)に変換したり、ループを展開(ループアンローリング)したり、命令の順番を変更するスケジューリングなどが行われる。
【0003】
コンパイラについては以下の特許文献に記載されている。
【先行技術文献】
【特許文献】
【0004】
【文献】特開2016-212573号公報
【文献】特開平09-160784号公報
【発明の概要】
【発明が解決しようとする課題】
【0005】
ベクトル命令は、ベクトル命令が処理する最初の配列からベクトル長の個数の配列を、メモリ内の連続するアドレスからロードし、ベクトルレジスタに格納し、ベクトル長の個数の配列要素を単一の命令コードで実行する。また、マスクレジスタ付きベクトル命令は、ベクトル長の配列要素のうちアクセスされる要素か否かを示すマスクビットに基づいて、メモリ内の配列の要素にアクセスする。
【0006】
一方、マイクロプロセッサは、命令列をデコードする際に、ストア命令とその後のロード命令がアクセスするメモリアドレスが互いに重なるか否かチェックし、チェック結果が真の場合は、プログラムコード順に、つまりストア命令を実行した後にロード命令を実行するルールで命令を実行する。このように、ロード命令が直前のストア命令の完了まで実行を待たされることを、SFI(Store Fetch Interlock)と呼ばれる。
【0007】
前述のマスクレジスタ付きベクトル命令は、マスクレジスタのマスクビットの一部がTRUE(アクセス要)で、残りのマスクビットがFALSE(アクセス不要)の場合、ベクトル長の配列要素の一部の要素しかアクセスしない。そのため、マスクレジスタ付きベクトル命令では、本来のSFIの発生は、連続するストア命令とロード命令それぞれのマスクレジスタのマスクビットに基づいて判定すべきである。
【0008】
しかしながら、マイクロプロセッサによっては、ベクトル命令について、連続するベクトルストア命令とベクトルロード命令が処理する最初の配列要素からベクトル長の個数の要素のデータのメモリアドレスが重なるか否かで、SFIの判定を行う。このように、ベクトル長の個数の要素のメモリアドレスは重なるが、ベクトル命令がマスクレジスタに基づきアクセスする配列要素のメモリアドレスは重ならない場合は、本来のSFIではなく、マイクロプロセッサのアーキテクチャに依存したSFIである。マイクロプロセッサのベクトル長が長くなると、ベクトル命令が処理する配列長が長くなり、ベクトル長の個数の配列要素のメモリアドレスの領域が長くなる。それに伴い、上記のアーキテクチャに依存したSFIの発生頻度が高くなる。
【0009】
マイクロプロセッサが、アーキテクチャに依存したSFIに基づいて連続するストア命令とロード命令をインオーダーで実行すると、アウトオブオーダーで実行する場合に比較して、命令の実行時間が長くなる。アーキテクチャに依存したSFIは、本来のSFIではなく連続するストア命令とロード命令をインオーダーで実行する必要はないので、アウトオブオーダーで実行させて実行時間を短くすることが望ましい。
【0010】
そこで、本実施の形態の第1の側面の目的は、ベクトル命令をアーキテクチャに依存したSFIの判定を回避するように最適化するコンパイラプログラム、コンパイル方法、情報処理装置を提供することにある。
【課題を解決するための手段】
【0011】
本実施の形態の第1の側面は、最適化対象プログラムについて最適化処理をコンピュータに実行させるコンパイラプログラムであって、
前記最適化対象プログラムは、配列変数のベクトルストア命令とベクトルロード命令を有するループを有し、
前記最適化処理は、
前記ループ内の前記ベクトルストア命令とベクトルロード命令を、ベクトル長を前記配列変数の配列サイズで除算して余りを切り上げた第1アンロール数または前記第1アンロール数より1つ少ない第2アンロール数だけアンローリングを行い、
前記アンローリングした複数のベクトルロード命令のうち先頭のベクトルストア命令より後ろのベクトルロード命令を、前記先頭のベクトルストア命令より前に移動させるスケジューリングを行う、コンパイラプログラムである。
【発明の効果】
【0012】
第1の側面によれば、コンパイラプログラムを実行するプロセッサが、ベクトル命令をアーキテクチャに依存したSFIの判定を回避するように最適化する。
【図面の簡単な説明】
【0013】
【
図1】コンパイラを実行する情報処理装置の構成例を示す図である。
【
図2】コンパイラによるコンパイル処理のフローチャートを示す図である。
【
図3】コンパイラによる最適化処理S102の詳細なフローチャートを示す図である。
【
図5】マスクレジスタ付ベクトルロード命令の配列の要素のメモリ上の位置とベクトルレジスタとマスクレジスタの関係例を示す図である。
【
図6】一重ループ化によるSFI_2を回避する方法を示す図である。
【
図7】アンパック化によるSFI_2を回避する方法を示す図である。
【
図8】アセンブリ擬似コードC22のベクトルロード命令vload(行05)とベクトルストア命令vstore(行07)のアクセスアドレスの関係を示す図である。
【
図9】アセンブリ擬似コードC23のベクトルロード命令vload(行05)とベクトルストア命令vstore(行07)のアクセスアドレスの関係を示す図である。
【
図10】一重ループ化またはアンパック化ではSFI_2を回避できない例を示す図である。
【
図11】実施の形態におけるSFI_2を回避する最適化処理(1)を示す図である。
【
図12】本実施の形態におけるSFI_2を回避する最適化処理のループアンローリングとスケジューリングを示す図である。
【
図13】ベクトル長VL=16の場合の配列サイズnに対応するセイル関数ceil(VL/n)の数の関係を示す図である。
【
図14】実施の形態におけるSFI_2を回避する最適化処理(2)を示す図である。
【
図15】本実施の形態におけるSFI_2を回避する最適化処理のループアンローリングとスケジューリングを示す図である。
【
図16】ループ内でロード命令がストア命令に先行するソースコードの場合のループアンローリングとスケジューリングを示す図である。
【
図17】ループ内でストア命令がロード命令に先行するソースコードの場合のループアンローリングとスケジューリングを示す図である。
【
図18】第2の実施の形態の最適化対象ループを有するソースコードとベクトル化後の中間擬似コードの例を示す図である。
【
図19】上記のループ(行03-06)をケース別ループに変換した分岐構造の中間擬似コードC42を示す図である。
【
図20】
図19のケース別ループに変換した分岐構造の中間擬似コードC42の各ケース別ループをそれぞれのアンロール数だけアンローリングした後の中間擬似コードC43を示す図である。
【
図21】第2の実施の形態の最適化対象ループを有するソースコードとベクトル化後の中間擬似コードの例を示す図である。
【
図22】ベクトル化後の中間擬似コードC51の最内ループ(行03-07)をケース別ループに変換した分岐構造の中間擬似コードC52を示す図である。
【
図23】
図22のケース別ループに変換した分岐構造の中間擬似コードC52の各ケース別ループをそれぞれのアンロール数だけアンローリングした後の中間擬似コードC53を示す図である。
【
図24】コンパイラの最適化処理の全体のフローチャートを示す図である。
【
図26】ループ構造分析S1の処理のフローチャートを示す図である。
【
図27】SFI_2の判定処理S20のフローチャートを示す図である。
【
図28】SFI_2の判定処理S20のフローチャートを示す図である。
【
図29】同じループ内及び前後のループ内のベクトルストア命令及びベクトルロード命令の関係性の判定処理S40のフローチャートを示す図である。
【
図30】同じループ内及び前後のループ内のベクトルストア命令及びベクトルロード命令の関係性の判定処理S40のフローチャートを示す図である。
【発明を実施するための形態】
【0014】
[用語の定義]
本明細書では、ベクトルストア命令とその後のベクトルロード命令がアクセスする配列要素のメモリアドレスが互いに重なる場合に発生する本来のSFIを、「一次SFI」または「SFI_1」と称する。また、ベクトルストア命令とその後のベクトルロード命令が、マスクレジスタに基づいてアクセスする配列要素のメモリアドレスは重ならない(一次SFIは起きない)が、ベクトル命令の先頭の配列要素からベクトル長の個数の配列要素のメモリアドレスが重なる場合、マイクロプロセッサのアーキテクチャに依存したSFIが発生する。このマイクロアーキテクチャに依存したSFIを、「二次SFI」または「SFI_2」と称する。また、「ベクトル命令の先頭の配列要素からベクトル長の個数の配列要素までのメモリアドレス」を、以下簡単の為に、「ベクトル命令のベクトル長の配列要素のメモリアドレス」と称する。
【0015】
コンパイラは、高水準言語プログラムであるソースコードから生成した中間コードを最適化し、アセンブリコードまたはオブジェクトコードに変換する。中間コードは、コンパイラに依存して様々な言語で記述される。そこで、本明細書では、中間コードを擬似的に記載した「中間擬似コード」を示して実施の形態の説明を行う。中間擬似コードは、アセンブリコードに類似するコードで記述する場合もある。同様に、アセンブリコードとして「アセンブリ擬似コード」を示す。
【0016】
[コンパイラを実行する情報処理装置及びコンパイル方法]
図1は、コンパイラを実行する情報処理装置の構成例を示す図である。情報処理装置1は、プロセッサであるセントラルプロセッサユニット(CPU)10と、プロセッサがアクセスするメインメモリ12と、外部とのインターフェース14と、補助記憶装置であるストレージ20と、それらを接続する内部バス16とを有する。
【0017】
ストレージ20には、コンパイラ21と、コンパイル対象のソースコード23と、コンパイラがソースコードから変換したアセンブリコードまたはオブジェクトコード25が格納される。また、コンパイラを実行中、メインメモリ12には、コンパイラがコンパイルするときに生成するパラメータ22とソースコードから生成した中間コード24とが格納される。プロセッサは、コンパイラ21をメモリ12内に展開し、展開されたコンパイラを実行する。ソースコードは、Fortran、C言語、C++などの高水準言語プログラムのコードである。中間コードは、コンパイラを実行するプロセッサが、ソースコードから生成したプログラムコードであり、コンパイル処理の最適化処理の対象である。
【0018】
図2は、コンパイラによるコンパイル処理のフローチャートを示す図である。プロセッサは、コンパイラを実行して次の処理を実行する。プロセッサは、コンパイル対象のソースコード23の解析を行う(S100)。ソースコードの解析は、例えば、ソースコードの字句解析、構文解析、意味解析等を含む。次に、プロセッサは、ソースコードの解析結果に基づいて、ソースコード23から中間コード24を生成する(S101)。そして、プロセッサは、中間コードを最適化処理し、演算時間を短くできる中間コードに変更する(S102)。最適化処理後に、中間コードをアセンブリコードに変換、またはオブジェクトコードに変換する(S103)。
【0019】
図3は、コンパイラによる最適化処理S102の詳細なフローチャートを示す図である。プロセッサは、コンパイラを実行して
図3に示した最適化処理S102を実行する。プロセッサは、中間コードに対して第1の最適化処理を実行する(S110)。第1の最適化処理は、例えば、多重ループ構造の一重ループ化などが含まれる。そして、プロセッサは、中間コードの複数のデータを処理する同じ命令コードをベクトル命令に置換するベクトル化を行う(S111)。そして、プロセッサは、ループ構造を分析し本実施の形態による最適化対象のループ構造を検出する(S112)。更に、プロセッサは、最適化対象のループ構造について、ループアンローリング(S112)、スケジューリング(S113)を実行する。最後に、プロセッサは、第2の最適化処理を実行する(S114)。
【0020】
ループアンローリングは、ループ内の命令を展開(アンローリング)してループ回数を減らす処理である。また、スケジューリングは、命令の順番を変更し、プロセッサがアウトオブオーダーで命令を実行できるようにする処理等である。
【0021】
[SFI_2]
図4は、SFI_2の発生例を示す図である。コードC1はソースコードの一例である。ソースコードC1では、単精度4byteの実数real(4)として配列a(8,32)とb(8,32)を宣言し(行02)、二次ループ(行03~07)内に、一次ループ(行04~06)が含まれる。最内(一次)ループ(行04~06)に、配列a(j,i)とb(j,i)を加算して配列a(j,i)に入力する演算命令が記載される(行05)。また、ベクトルレジスタのサイズを512bitとし、上記の通り配列の要素のサイズが単精度の4byteとすると、ベクトル長VL(Vector Length)は以下のとおりである。
ベクトル長VL=ベクトルレジスタのサイズ(512bit)/配列の要素のサイズ(4byte)=16
つまり、ベクトル長VLは、ベクトル命令が処理できる配列の最大要素数である。ベクトルレジスタのサイズを512bit、配列の要素サイズを倍精度の8byteとすると、ベクトル長VLは8となる。
【0022】
ソースコードC1の最内ループの演算命令をベクトル化すると、ベクトル化された中間擬似コードC2が生成される。中間擬似コードC2では、ソースコードC1の最内ループの演算命令がベクトル化され、配列a(1:8,i)とb(1:8,i)を加算して配列a(1:8,i)に入力する演算命令(行04)に変更されている。中間擬似コードC2は、ソースコードC1と同様のコードで擬似的に表現されている。
【0023】
そこで、コードC2がアセンブリコードに変換されると、アセンブリ擬似コードC3となる。アセンブリ擬似コードC3には主要な命令のみが抜粋して記載される。コードC2のループ(行03~05)が、コードC3では、ロード命令、add命令、ストア命令、減算命令のアセンブリコードを含むループ(行03~09)に変換されている。行02と行04~07と行08のコードの意味は次の通りである。
行02:マスクレジスタpredicate_true ps0は、要素が4byte(ps:predicate single)であり、先頭の8要素がTRUEで残りの8要素がFALSEである。具体的なマスクレジスタMASKが行02の右側に示されている。
行04:配列b(1:8,i)の1~8要素のデータをメモリからベクトルレジスタvs2にロードするマスクレジスタps0付きベクトルロード命令vload。ベクトルレジスタvs2は要素が単精度の4byte(vs:vector single)である。
行05:配列a(1:8,i)の1~8要素のデータをメモリからベクトルレジスタvs1にロードするマスクレジスタps0付きベクトルロード命令vload。ベクトルレジスタvs1も配列要素が単精度の4byteである。
行06:ベクトルレジスタvs1とvs2を加算し、vs1に格納する。
行07:ベクトルvs1のデータをメモリ内の配列a(1:8,i)にストアするマスクレジスタps0つきベクトルストア命令vstore。
行08:ループの制御変数iを格納するレジスタd2の値を-1する。
【0024】
図5は、マスクレジスタ付ベクトルロード命令の配列の要素のメモリ上の位置とベクトルレジスタとマスクレジスタの関係例を示す図である。
図4と同様にベクトルレジスタサイズが512ビット、配列の要素サイズが4byte、レジスタ長VLが16である。メモリ上には、配列a(8,32)の各要素のデータが、a(1,1)~a(8,1), a(1,2)~a(8,2)の順に、連続するアドレスに記憶される。ベクトルレジスタサイズが512bitで、配列の1つの要素のサイズが4byte(単精度)の場合、前述したとおりベクトル長は16になり、16個の配列要素は16×4byte×8bit = 512 bitの容量でメモリ内に記憶される。図中、VLの矢印が、先頭の配列要素からベクトル長VL個の配列要素までのメモリ上のアドレスの領域を示す。
【0025】
そして、ベクトルロード命令では、プロセッサは、メモリ内の16個の配列要素のデータにアクセスし、16個の要素をベクトルレジスタに格納する。逆にベクトルストア命令では、プロセッサは、512bitのベクトルレジスタ内に格納される16個の配列要素を、512bitの容量でメモリ内に記憶する。
【0026】
図中一番上のマスクレジスタ付ベクトルロード命令vloadは、そのマスクレジスタMASKの最初の8要素がTRUE(T)であり、後半の8要素がFALSE(F)である。このマスクレジスタ付ベクトルロード命令を実行すると、プロセッサは、マスクレジスタに基づいて、メモリ上の配列a(8,32)の8要素a(1,1)~a(8,1)をベクトルレジスタの8個の要素にロードする。この場合、プロセッサは、ベクトルロード命令が処理する1番目の要素a(1,1)のアドレスから8番目の要素a(8,1)のアドレスまでメモリにアクセスし、8要素のロードしたデータをベクトルレジスタの8個の要素に格納する。
【0027】
二番目のマスクレジスタ付ベクトルロード命令vloadは、そのマスクレジスタの16要素のうち先頭の4要素がTRUE(T)で、残りの12要素がFALSE(F)である。この場合、プロセッサは、マスクレジスタに基づいて、メモリ上の配列a(8,32)の4要素a(1,1)~a(4,1)のアドレスにアクセスし、読みだした4要素のデータをベクトルレジスタの先頭の4個の要素にロードする。
【0028】
このようにマスクレジスタ付きベクトル命令を実行すると、プロセッサは、ベクトル長VLの全要素のうち一部の要素についてメモリにアクセスし、ベクトルレジスタに一部の要素を格納またはベクトルレジスタの一部の要素をメモリに記憶する。マスクレジスタは、通常、コンパイラがアセンブリコードまたはオブジェクトコードを生成するときにコードC3のように生成する。コンパイラは、ベクトル命令がベクトル長の全要素を処理しない場合、マスクレジスタを生成する。
【0029】
図4に戻り、コードC3がプロセッサにより実行されると、
図4の最下に示したとおり、1回目のループのベクトルストア命令vstore1と2回目のループのベクトルロード命令vload2がマスクレジスタに基づいてアクセスする要素(マスクレジスタがTRUEの要素)のメモリアドレスは重なっていない。但し、ベクトル命令vstore1とvload2のベクトル長VLの配列要素のメモリアドレス(矢印VLのメモリアドレス)は一部で重なっている。この場合、両ベクトル命令がマスクレジスタに基づいてアクセスする要素のメモリアドレスは重なっていないので、SFI_1は発生せず、一方で、両ベクトル命令のベクトル長VLの配列要素のメモリアドレスでは一部で重なっているので、SFI_2が発生する。
【0030】
したがって、プロセッサのデコーダがコードC3を解析すると、SFI_2が発生すると判定され、隣接するベクトル命令vstore1とvload2がインオーダーで実行される。その結果、プロセッサがアウトオブオーダーで実行しないため処理時間が長くなる。
【0031】
[一重ループ化によるSFI_2回避]
図6は、一重ループ化によるSFI_2を回避する方法を示す図である。
図6のソースコードC10は、
図4のソースコードC1と同じである。
図4では、ベクトル長VL=16に対して最内ループでは制御変数j = 1~8で回転する。そのため、最内ループの命令をベクトル命令に変換すると、ベクトル命令はベクトル長16の要素のうち先頭の8要素のデータにアクセスする。その結果、前のベクトルストア命令vstore1と後ろのベクトルロード命令vload2は、それぞれがマスクに基づいてアクセスする要素のアドレスは互いに重ならないが、ベクトル長VL=16の要素のアドレスでは互いに重なり、SFI_1は発生しないがSFI_2が発生した。
【0032】
それに対して、
図6の例では、コンパイラを実行するプロセッサは、ソースコードC10の最内ループ(行04~06)を削除して一重ループ化した中間コードC12を生成し、更に、ベクトル長16と同じ数の要素にアクセスするベクトル命令(行04)に変換した中間擬似コードC13を生成する。中間擬似コードC13のベクトル命令(行04)は、次のとおりである。
a(1:16,i) = a(1:16,i) + b(1:16,i)
つまり、ベクトル命令のデータ数(要素数)はベクトル長VL=16と等しく、ループの制御変数iは1~256で16飛びに変更されている。
【0033】
コンパイラを実行するプロセッサは、中間擬似コードC13からアセンブリ擬似コードC14を生成する。このアセンブリ擬似コードC14では、マスクレジスタps0がベクトル長16の全要素でTRUEとなる。その結果、アセンブリ擬似コードC14の場合、配列a(1:16, i)のベクトルストア命令vstore1とベクトルロード命令vload2がアクセスする16要素のアドレスは、互いに重ならない。つまり、SFI_1もSFI_2も発生しない。
【0034】
このように、ソースコードC10の変数a(8:32)の配列サイズ8と、最内ループ(行04-06)の回転数8(j=1-8)とが一致する場合、ループを跨いで連続するストア命令とロード命令がメモリ上の連続するアドレスの要素データにアクセスするため、最内ループを削除して一重ループ化することでストア命令とロード命令が連続アドレスにアクセスするようにする。つまり、両命令をベクトル長16の要素のベクトル命令に変換すると、SFI_1は発生せず、またSFI_2を回避可能になる。
図6のアセンブリ擬似コードC14の下には、1回転目のベクトルストア命令vstore1と2回転目のベクトルロード命令vload2それぞれがアクセスするベクトル長16の16要素のアドレスが重ならないことが示される。
【0035】
[アンパック化によるSFI_2回避]
図7は、アンパック化によるSFI_2を回避する方法を示す図である。
図7のソースコードC20では、配列変数a(9,32)、b(9,32)に対し、最内ループ(行04-06)は回転数8(j=1-8)である。つまり、配列変数a(9,32)の配列サイズnはn=9であるのに対して、最内ループの回転数mはm=8と、両者は異なっている。
【0036】
ソースコードC20の最内ループの命令をベクトル化すると、中間擬似コードC21が生成される。更に、中間擬似コードC21をアセンブリコードに変換するとアセンブリ擬似コードC22が生成される。アセンブリ擬似コードC22では、マスクレジスタps0は単精度singleの配列に対応し、ベクトル長16のうち8要素がTRUE、残りの8要素がFALSEである。このアセンブリ擬似コードC22の変数aについてのベクトルロード命令vload(行05)とベクトルストア命令vstore(行07)のアクセスアドレスの関係は、
図8に示されるとおりになる。
【0037】
図8は、アセンブリ擬似コードC22のベクトルロード命令vload(行05)とベクトルストア命令vstore(行07)のアクセスアドレスの関係を示す図である。
図8には、1回転目のベクトルストア命令vstore1のマスクレジスタMASKとメモリ上の変数aの配列要素a(1,1) - a(9,1), a(1,2) - a(7,2)と、2回転目のベクトルロード命令vload2のマスクレジスタMASKとメモリ上の変数aの配列要素a(1,2) - a(9,2), a(1,3) - a(2,3)が示される。この場合、配列サイズ9に対してループ回転数8であり、配列要素a(9,1)はアクセスされないので、連続アドレスにはアクセスされない。
図8の処理順とメモリアドレスの関係に示されるように、1回転目のベクトルストア命令vstore1と2回転目のベクトルロード命令vload2では、それぞれがアクセスするメモリ上のアドレス(マスクレジスタがTRUEの要素のアドレス)は重ならないが、両命令のベクトル長VL=16の要素のアドレスは重なる。つまり、SFI_1は発生しないが、SFI_2が発生する可能性がある。
【0038】
図7に戻り、そこで、コンパイラを実行するプロセッサは、アセンブリ擬似コードC22からアセンブリ擬似コードC23を生成する。具体的には、コンパイラを実行するプロセッサは、アンパック命令を利用して、アセンブリ擬似コードC22の命令を、1要素のサイズを4byteから8byteと二倍に変更し、ベクトル長16のベクトル命令をベクトル長8のベクトル命令に変更する。
【0039】
図5内のunpackedに、アンパック命令におけるメモリ上の配列aとベクトルレジスタとの関係が示される。
図5では単精度4byteでベクトル長VL=16の例である。
図5に示されるとおり、それぞれ4byteの8要素は、ベクトルレジスタ内のそれぞれ8byteの8要素の上位ビット側(または下位ビット側)にそれぞれ格納され、下位ビット側(または上位ビット側)は0等にされる。つまり、VL=16において、ベクトルレジスタ内の各4byteの要素に16個のデータが格納されるのがパック命令であるのに対して、アンパック命令では各8byteの要素に8個のデータが格納される。つまり、アンパック命令ではベクトルレジスタ内に8byte間隔で4byteのデータが8個格納される。
【0040】
図7のアセンブリ擬似コードC23では、倍精度8byteの要素に対応する倍精度のマスクレジスタpd0の全要素(8要素)が全てTRUEであり、配列長8のベクトル命令vload, vstoreのベクトルレジスタvd1, vd2はいずれも倍精度(vd: vector double)の8要素を有する。そのため、アセンブリ擬似コードC23の変数aについてのベクトルロード命令vload(行05)とベクトルストア命令vstore(行07)のアクセスアドレスの関係は、
図9に示されるとおりになる。
【0041】
図9は、アセンブリ擬似コードC23のベクトルロード命令vload(行05)とベクトルストア命令vstore(行07)のアクセスアドレスの関係を示す図である。
図9には、1回転目のベクトルストア命令vstore1のマスクレジスタMASKとメモリ上の変数aの配列要素a(1,1) - a(9,1)と、2回転目のベクトルロード命令vload2のマスクレジスタMASKとメモリ上の変数aの配列要素a(1,2) - a(2,2)が示される。左右方向がメモリのアドレスに対応する。1回転目のベクトルストア命令vstore1がマスクレジスタに基づいてアクセスする8要素のメモリ上のアドレスと、2回転目のベクトルロード命令vload2がマスクレジスタに基づいてアクセスする8要素のメモリ上のアドレスは重ならない。これによりSFI_1が発生しないことは変わらない。そして、1回転目のベクトルストア命令vstore1のベクトル長8の個数の要素のアドレスと、2回転目のベクトルロード命令vload2のベクトル長8の個数の要素のアドレスも、重ならない。これによりSFI_2が回避される。
【0042】
図9の縦軸の処理順と横軸のメモリアドレスの関係に示されるとおり、1回転目のベクトルストア命令vstore1がアクセスするベクトル長8の個数の要素のアドレスと、2回転目のベクトルロード命令vload1がアクセスするベクトル長8の個数の要素のアドレスが重なっていないので、SFI_2は回避されることが理解できる。
【0043】
上記の通り、配列サイズnがn=9でループの回転数mがm=8のように、配列サイズnとループ回転数mが一致しない(m<n)場合、連続したアドレスアクセスができず、一重ループ化は利用できない。しかし、ループ回転数mとベクトル長VLが1:2のように特定の比率であれば、アンパック化により、SFI_2を回避することができる。
【0044】
[一重ループ化またはアンパック化ではSFI_2を回避できない例]
図10は、一重ループ化またはアンパック化ではSFI_2を回避できない例を示す図である。
図10に示したソースコードC30は、配列変数a(4,32)の配列サイズnがn=4で、最内ループ(行04-06)のループ回転数mがm=3と、m<nである。そして、ソースコードC30の最内ループ内の演算命令をベクトル化すると、中間擬似コードC31が生成される。この例は、最内ループ内は、ロード命令の後にストア命令がある例(ロード後ストア)である。
【0045】
図10には、中間擬似コードC31のループ(行03-05)の1回転目のベクトルロード命令vload1及びベクトルストア命令vstore1のマスクレジスタMASKとメモリ上の配列と、2~4回転目のベクトルロード命令vload2, vload3, vload4のメモリ上の配列が示される。これによれば、1回転目のベクトルストア命令vstore1がマスクに基づいてアクセスする要素と、2~4回転目のベクトルロード命令vload2~vload4がマスクに基づいてアクセスする要素とはアドレスが重ならない。しかし、1回転目のベクトルストア命令vstore1のベクトル長16の要素のメモリアドレスと、2~4回転目のベクトルロード命令vload2~vload4のベクトル長16の要素のメモリアドレスが重なる。よって、SFI_1は発生しないが、SFI_2が発生する可能性がある。
【0046】
前述の通り、ソースコードC30では、配列変数a(4,32)の配列サイズn=4と、最内ループ(行04-06)のループ回転数m=3(ベクトル命令のアクセス要素数と同じ)とが、m<nと一致せず、最内ループを繰り返した場合ベクトル命令が連続アドレスへアクセスしない。また、ループ回転数m=3は、ベクトル長VL=16と1:2,1:4等、アンパック命令を利用できる特定の比率ではない。よって、
図10のソースコードC30の例では、前述した一次ループ化またはアンパック化ではSFI_2を回避することはできない。
【0047】
[第1の実施の形態例、変数の配列サイズnとループ回転数mとベクトル長VLが定数の例]
[ループ内でロード命令の後にストア命令がある例(ロード後ストア)]
第1の実施の形態では、コンパイラを実行するプロセッサが、
図10に示した配列サイズnとループ回転数mとがm<nと異なり且つループ回転数mがベクトル長VLと前述の特定の比率ではないループを、最適化する。また、第1の実施の形態では、最適化対象ループの変数の配列サイズnとループ回転数mとベクトル長VLが定数の例である。
【0048】
図11は、実施の形態におけるSFI_2を回避する最適化処理(1)を示す図である。最内ループ内がロード命令の後にストア命令がある例(ロード後ストア)である。
図11には、
図10のソースコードC30とその最内ループの演算命令をベクトル化した中間擬似コードC31が示される。
【0049】
図10には、中間擬似コードC31をアセンブリコードに変換した場合の1回転目のベクトルロード命令vload1及びベクトルストア命令vstore1のメモリ上の配列a(1,1)-a(4,4)と、2~4回転目のベクトルロード命令vload2, vload3, vload4のメモリ上の配列a(1,1)-a(4,4)とが示される。各ループでは制御変数iが1~32にインクリメントされ、制御変数jについてはj = 1 - 3の配列がベクトル命令でアクセスされる。つまり、1回転目では配列a(1,1)-a(3,1)が、2回転目では配列a(1,2)-a(3,2)が、3回転目では配列a(1,3)-a(3,3)が、4回転目では配列a(1,4)-a(3,4)が、それぞれのベクトル命令でアクセスされる。そして、1回目のベクトルストア命令vstore1がアクセスする配列a(1,1)-a(3,1)のアドレスは、2~4回目のベクトルロード命令vload2, vload3, vload4がそれぞれアクセスする配列のアドレスとは、重なっていない。このことは、1回目のベクトルストア命令vstore1と、その後の2~4回目のベクトルロード命令vload2, vload3, vload4との間では、SFI_1は発生しないことを意味する。但し、1回目のベクトルストア命令vstore1のベクトル長16の要素のアドレスと、2~4回転目のベクトルロード命令vload2, vload3, vload4のベクトル長16の要素のアドレスそれぞれとが重なるので、SFI_2が発生する可能性がある。
【0050】
そこで、
図11に示す本実施の形態では、コンパイラを実行するプロセッサが、ベクトル化後の中間擬似コードC31のベクトル演算命令(行04)を有する最内ループ(行03-06)を、4アンローリングを行って、中間擬似コードC32を生成する。中間擬似コードC31のループ(行03-05)が、中間擬似コードC32では行03-08のアンローリングされたループに変更されている。4アンローリングにより、中間擬似コードC32のループ(行03-08)には、以下の4つのベクトル演算命令が含まれる。これら4つのベクトル演算命令は、元のコードC31の1~4回転目(i = 1-4)の演算命令である。
a(1:3,i) = a(1:3,i) + b(1:3,i)
a(1:3,i+1) = a(1:3,i+1) + b(1:3,i+1) // 元2回転目
a(1:3,i+2) = a(1:3,i+2) + b(1:3,i+2) // 元3回転目
a(1:3,i+3) = a(1:3,i+3) + b(1:3,i+3) // 元4回転目
これに伴い、行03のDO文では、制御変数iが4つ飛びで32までインクリメントされる。
【0051】
アンローリングの数を4としたのは、ベクトル長VL=16と変数aの配列サイズn=4の除算の余りを切り上げる関数、セイルceil(VL/n)=ceil(16/4)=4に基づく。すなわち、
図10に示したとおり、1回転目のベクトルストア命令vstore1のベクトル長の要素のアドレスと、1~4回転目のベクトルロード命令vload1~vload4のマスクに基づきアクセスする要素(それぞれ3個の要素)のアドレスが重なり、5回転目以降のベクトルロード命令のマスクに基づきアクセスする要素のアドレスとは重ならない。これが4アンローリングの理由である。
【0052】
図12は、本実施の形態におけるSFI_2を回避する最適化処理のループアンローリングとスケジューリングを示す図である。
図12には、
図10と同様の1回転目のベクトルストア命令vstore1のベクトル長の要素のアドレスと、1~4回転目のベクトルロード命令vload1~vload4のマスクに基づきアクセスする要素(それぞれ3個の要素)のアドレスが示される。
【0053】
図12に示すとおり、4アンローリング(unrolling)により、1回転目のベクトルストア命令vstore1の後ろ(垂直方向の下)に2~4回転目のベクトルロード命令vload2~vload4が位置する。一方、1回転目のベクトルロード命令vload1は、1回転目のベクトルストア命令vstore1より前(垂直方向の上)に位置する。そして、1回転目のベクトルストア命令vstore1のアクセスアドレスは、2~4回転目のベクトルロード命令vload2~vload4のアクセスアドレスとは重なっておらず、本来のSFIであるSFI_1は発生しない。
【0054】
そして、コンパイラを実行するプロセッサは、4アンローリングしたベクトル演算命令のうち2~4回転目のベクトルロード命令vload2~vload4を、1回転目のベクトルストア命令vstore1の前に移動させるスケジューリングを実行する。
図12に示すスケジューリング(Scheduling)の破線矢印に示す命令の移動である。このスケジューリングをした結果、コンパイルされたオブジェクトコードを実行するプロセッサは、1~4回転目のベクトルロード命令vload1~vload4が1回転目のベクトルストア命令vstore1より前に位置するので、両命令間でSFI_2が発生せず、オブジェクトコードを実行するプロセッサはSFIを検出しない。そのため、プロセッサは、1~4回転目のベクトルロード命令vload1~vload4を1回転目のベクトルストア命令vstore1より前に実行でき、4つのベクトルロード命令をアウトオブオーダーで実行することもでき、4命令を並列実行するなどにより演算時間を短縮できる。
【0055】
図11には、ループアンローリングされた中間擬似コードC32のスケジューリングの処理が擬似的に示される。中間擬似コードC33は、中間擬似コードC32の4つのベクトル演算命令からロード命令(temp#=a(1:3,#) 但し、#=1-4)を抽出して生成した。抽出されたロード命令は、変数a(1:3,#)をレジスタtemp#に入力する命令である。それに伴い、変数a(1:3,#)に、レジスタtemp#と変数b(1:3,#)の和がストアされている。
【0056】
そして、コンパイラを実行するプロセッサが、中間擬似コードC33の2~4回転目のベクトルロード命令vload2~vload4を、1回転目のベクトルストア命令vstore1より前に移動するスケジューリングを行って、中間擬似コードC34を生成する。
【0057】
アンローリングの数は、ベクトルストア命令のベクトル長の要素のアドレスと、マスクに基づきアクセスする要素のアドレスが重なるベクトルロード命令の数である。つまり、前述した、ベクトル長VLと変数aの配列サイズnについてのセイル関数ceil(VL/n)の数である。
【0058】
図13は、ベクトル長VL=16の場合の配列サイズnに対応するセイル関数ceil(VL/n)の数の関係を示す図である。ベクトル長VL=16で、変数aの配列サイズnがn<VLを満たす場合、n=1~15である。
図13には、n=1~16に対するセイル関数ceil(VL/n)の数と、ceil(VL/n)-1の数とが示される。
図11、
図12に示した配列サイズn=4の場合は、セイル関数ceil(VL/n)の数が4になっている。
【0059】
[ループ内がロード命令の後にストア命令があるロード後ストアの例]
図14は、実施の形態におけるSFI_2を回避する最適化処理(2)を示す図である。最内ループ内にストア命令の後にロード命令があるストア後ロードの例である。ソースコードC30_2では、最内ループ(行04-07)に、メモリ内の配列変数aへのストア命令(行05)とメモリ内の配列変数aからのロード命令(行06)が示される。中間擬似コードC31_2では、最内ループで繰り返す複数の命令がベクトル命令(行04-05)に変換されている。
【0060】
図15は、本実施の形態におけるSFI_2を回避する最適化処理のループアンローリングとスケジューリングを示す図である。
図15には、中間擬似コードC31_2をアセンブリコードに変換した場合の1回転目のベクトルストア命令vstore1のベクトル長VLのメモリ上の配列a(1,1)-a(4,4)と、1~3回転目のベクトルロード命令vload1, vload2, vload3のメモリ上の配列a(1,2)-a(4,2), a(1,3)-a(4,3), a(1,4)-a(4,4)とが示される。各ループでは制御変数iが1~32にインクリメントされ、制御変数jについてはj = 1-3の配列がベクトル命令でアクセスされる。ベクトルロード命令では、1回転目では配列a(1,2)-a(3,2)が、2回転目では配列a(1,3)-a(3,3)が、3回転目では配列a(1,4)-a(3,4)が、それぞれのベクトル命令でアクセスされる。そして、1回目のベクトルストア命令vstore1がマスクに基づきアクセスする配列a(1,1)-a(3,1)のアドレスは、1~3回目のベクトルロード命令vload1, vload2, vload3がそれぞれマスクに基づきアクセスする配列のアドレスとは、重なっていない。このことは、1回目のベクトルストア命令vstore1と、その後の1~3回目のベクトルロード命令vload1, vload2, vload3との間では、SFI_1は発生していないことを意味する。但し、SFI_2が発生する可能性がある。
【0061】
図14に戻り、本実施の形態では、コンパイラを実行するプロセッサが、ベクトル化後の中間擬似コードC31_2のベクトル演算命令(行04-05)を、3アンローリングして、中間擬似コードC32_2を生成する。中間擬似コードC31_2のループ(行03-06)が、中間擬似コードC32_2では行03-10のループに変更されている。3アンローリングにより、中間擬似コードC32_2のループ(行03-10)には、以下の3つのベクトル演算命令が含まれる。これら3つのベクトル演算命令は、元のコードC31_2の1~3回転目(i = 1-3)の演算命令である。
a(1:3,i) = b(1:3,i)
c(1:3,i) = a(1:3,i+1) + i
a(1:3,i+1) = b(1:3,i+1) // 元2回転目
c(1:3,i+1) = a(1:3,i+2) + i+1 // 元2回転目
a(1:3,i+2) = b(1:3,i+2) // 元3回転目
c(1:3,i+2) = a(1:3,i+3) + i+2 // 元3回転目
これに伴い、行03のDO文では、制御変数iが3つ飛びでインクリメントされる。
【0062】
アンローリングの数を3としたのは、セイルceil(VL/n)-1=ceil(16/4)-1=3に基づく。すなわち、1回転目のベクトルストア命令vstore1のベクトル長の要素のアドレスと、1~3回転目のベクトルロード命令vload1~vload3のマスクに基づきアクセスする要素のアドレスが重なり、4回転目以降のベクトルロード命令のマスクに基づきアクセスする要素のアドレスとは重ならない。これが3アンローリングの理由である。
【0063】
図15には、
図12と同様の1回転目のベクトルストア命令vstore1のベクトル長の要素のアドレスと、1~3回転目のベクトルロード命令vload1~vload3がマスクに基づきアクセスする要素のアドレスが示される。
図15に示すとおり、3アンローリングにより、1回転目のベクトルストア命令vstore1の後ろに1~3回転目のベクトルロード命令vload1~vload3が位置する。そして、1回転目のベクトルストア命令vstore1のマスクに基づくアクセスアドレスは、1~3回転目のベクトルロード命令vload1~vload3のマスクに基づくアクセスアドレスとは重なっておらず、本来のSFIであるSFI_1は発生しない。
【0064】
そこで、本実施の形態では、コンパイラを実行するプロセッサは、3アンローリングしたベクトル演算命令のうち1~3回転目のベクトルロード命令vload1~vload3を、1回転目のベクトルストア命令vstore1の前に移動させるスケジューリングを実行する。
図14に示すスケジューリング(Scheduling)の破線矢印に示す命令の移動である。このスケジューリングをした結果、コンパイルされたオブジェクトコードを実行するプロセッサは、1~3回転目のベクトルロード命令vload1~vload1が1回転目のベクトルストア命令vstore1より前に位置するので、両命令間でSFI_2を検出しない。そのため、プロセッサは、1~3回転目のベクトルロード命令vload1~vload3を1回転目のベクトルストア命令vstore1より前に実行でき、3つのベクトルロード命令をアウトオブオーダーで実行することもでき、並列実行などにより演算時間を短縮できる。
【0065】
図15には、ループアンローリングされた中間擬似コードC32_2のスケジューリングの処理が擬似的に示される。中間擬似コードC33_2と、スケジューリング後の中間擬似コードC34_2は、
図11のコードC33とC34に対応する。よって、詳細な説明は省略する。
【0066】
最内ループ内がストア後ロードの例では、アンローリングの数は、ベクトルストア命令のベクトル長の要素のアドレスと、マスクに基づきアクセスする要素のアドレスが重なるベクトルロード命令の数である。1回目のループでベクトルストア命令vstore1とベクトルロード命令vload1の配列の位置がずれているので、アンローリングの数は、ベクトル長VLと変数aの配列サイズnについてのセイル関数から1減じたceil(VL/n)-1の数である。
図11,12の例より1つ少ない数である。
【0067】
[ループ内がロード後ストアの例とストア後ロードの例のまとめ]
[ループ内がロード後ストアの例]
図16は、ループ内でロード命令がストア命令に先行するソースコードの場合のループアンローリングとスケジューリングを示す図である。
図11と同様に、先行するロード命令とその後ろのストア命令は、同じ変数の同じ要素にアクセスする命令である。
図16には、ループアンローリング後とスケジューリング後における、各ループのベクトルストア命令Svstoreベクトルロード命令vloadとのメモリアドレス(横方向)の関係が示される。図中ベクトル長VLは、1回転目のストア命令vstore1がアクセスするベクトル長の要素のメモリアドレスの位置を示す。
【0068】
本実施の形態が対象としているのは、SFI_2を回避することができるループ構造であり、ループ回転数mが配列サイズより小さく(m<n)で、配列サイズnがベクトル長VL以下(n=<VL)のループ構造である。よって、ベクトルロード命令vloadとベクトルストア命令のマスクレジスタは、配列の最初のm個の要素でTRUE(T)、またその後ろn-m個の要素でFALSE(F)、更にその後ろのVL-n個の要素もFALSE(F)である。そして、1回転目のループと2回転目のループでは、両命令の最初要素のアドレスが配列サイズn個ずつずれている。3回転目以降も同様である。したがって、
図11と同様にVL=16、n=4とすると、1回転目のベクトルストア命令vstore1と2~4回転目のベクトルロード命令vload2~vload4との間でSFI_2が発生する可能性がある。
【0069】
この例では、コンパイラを実行するプロセッサが、最適化対象ループに対して4アンローリングを実行して、図示されるように1~4回転目までのベクトルロード命令vloadとベクトルストア命令vstoreを展開(アンローリング)する。そして、コンパイラを実行するプロセッサが、先頭のベクトルストア命令vstore1の後ろの2~4回転目のベクトルロード命令vload2~vload4を、先頭のベクトルストア命令vstore1の前に移動するスケジューリングを行う。スケジューリング後の状態から理解できるとおり、4つのベクトルロード命令vload1~vload4は4つのベクトルストア命令vstore1~vstore4の前にあるので、コンパイルされたオブジェクトコードを実行するプロセッサによってSFI_2と判定されることはない。そして、プロセッサは、4つのベクトルロード命令vload1~vload4をアウトオブオーダーで実行することができる。
【0070】
[ループ内がストア後ロードの例]
図17は、ループ内でストア命令がロード命令に先行するソースコードの場合のループアンローリングとスケジューリングを示す図である。
図14と同様に、同じループ内の先行するストア命令とその後ろのロード命令は、同じ変数の異なる要素にアクセスする命令である。そして、1回転目のループでは、ストア命令とロード命令の先頭要素のアドレスが配列サイズn個ずつずれている。2回転目以降も同様である。したがって、VL=16、n=4とすると、1回転目のベクトルストア命令vstore1と1~3回転目のベクトルロード命令vload1~vload3との間でSFI_2が発生する可能性がある。
【0071】
この例では、コンパイラを実行するプロセッサが、最適化対象のループに対して3アンローリングを実行して、図示されるように3回転目までのベクトルロード命令vloadとベクトルストア命令vstoreを展開(アンローリング)する。そして、プロセッサが、先頭のベクトルストア命令vstore1の後ろの1~3回転目のベクトルロード命令vload1~vload3を、先頭のベクトルストア命令vstore1の前に移動するスケジューリングを行う。スケジューリング後の状態では、3つのベクトルロード命令vload1~vload3は3つのベクトルストア命令vstore1~vstore3の前にあるので、オブジェクトコードを実行するプロセッサによってSFI_2と判定されることはない。そして、プロセッサは、3つのベクトルロード命令vload1~vload3を、アウトオブオーダーで実行することができる。
【0072】
[第2の実施の形態例、変数の配列サイズnとループ回転数mが変数でベクトル長VLが定数または不明の例]
第2の実施の形態も、コンパイラを実行するプロセッサが、
図10に示した配列サイズnとループ回転数mとがm<nと異なり、ループ回転数mとベクトル長VLとの比が前述のアンパック化を適用できる比ではないループを最適化する。更に、第2の実施の形態では、最適化対象ループの変数の配列サイズnとループ回転数mが変数で、ベクトル長VLが定数または不明の例である。但し、n>VLの例は、最適化対象ループから除く。ここで、変数の配列サイズnとループ回転数mが変数とは、コンパイルされたオブジェクトコードをプロセッサが実行したときに両変数の値が確定し、コンパイル時は両変数が確定しないことを意味する。また、ベクトル長VLが不明とは、ソースプログラムをコンパイルしたオブジェクトコードを実行するプロセッサのベクトル長がコンパイル時に不明であることである。
【0073】
[ループ内がロード命令の後にストア命令の例]
図18は、第2の実施の形態の最適化対象ループを有するソースコードとベクトル化後の中間擬似コードの例を示す図である。この例は、最内ループ(行04-06)内でロード命令の後にストア命令がある例である。ソースコードC40では、配列変数a(n,32), b(n,32), c(n,32)の配列サイズnが変数であり、最内ループの回転数mが変数であり、そして、ベクトル長VLが定数または不明である。この場合、論理的にm=<nであり、n>VLのループを最適化対象ループから除くとすると、m=<VLが保証される。
【0074】
ソースコードC40の最内ループを回転数mでベクトル化すると、ベクトル化後の中間擬似コードC41が生成される。中間擬似コードC41では、C40の最内ループ(行04-06)が、以下の演算命令に変換されている。
【0075】
do j = 1, m, VL //VL: 16
a(j:j+VL-1,i) = a(j:j+VL-1,i) + b(j:j+VL-1,i)
enddo
ベクトル化後の中間擬似コードC41の場合、配列サイズnとベクトル長VLの関係によっては、SFI_2に該当する場合がある。この場合のSFI_2は、
図10で説明したように、ベクトルストア命令とその後のベクトルロード命令との間で、両命令のベクトル長の要素のアドレスは重なるが、両命令がマスクに基づきアクセスする要素のアドレスは重ならない場合である。
【0076】
このようなループについて、本実施の形態では、コンパイラがSFI_2を回避する最適化処理を行う。SFI_2を回避する最適化処理の概略は次の通りである。
【0077】
(1)ソースコード内で配列変数の宣言された配列サイズnが変数の場合、コンパイル時は配列サイズnが不明である。そこで、ベクトル化後のコードC41のループ(行03-06)を、ベクトル長VLを配列サイズnで除算して余りを切り上げる関数ceil(VL/n)(またはループ内にストア命令の後にロード命令がある場合はceil(VL/n)-1)の数別(ケース別)に、それぞれ最内ループ(行03-06)内のベクトルロード命令とベクトルストア命令を有する、ケース別ループに変換する。
【0078】
図19は、上記のループ(行03-06)をケース別ループに変換した分岐構造の中間擬似コードC42を示す図である。コードC42は、ベクトル長VLをVL=16の例である。コードC42において、行02-34が、ベクトル長VLが後述するベクトル長配列VL_array(SFI_2が起こるVLを格納した配列)に含まれる場合で且つn<=VLという条件を有するif文の条件が真の場合のケース別ループである。行35-42が、if文の条件が偽の場合のループである。
【0079】
行02-34のケース別ループでは、行03のselect文の条件ceil(VL/n)が0~16の場合に対応するケース0-16(case 0 ~ case 16)それぞれに、コードC41の最内ループ(行04-06)のベクトル演算命令(行04)が記載される。if文の条件n<=VLの場合m<=VLが満たされるので、コードC41の最内ループ(行04-06)のベクトル演算命令は、
図19のコードC42では、例えば行06-08のコードとされる。以下のとおりである。
06 do i = 1, 32
07 a(1:m,i) = a(1:m,i) + b(1:m,i)
08 enddo
図13のceil(VL/n)に示したとおり、配置サイズnがn=8~15の場合ceil(VL/n)=2であるので、
図19のコードC42では、ケース2(case 2)に該当する。
【0080】
(2)次に、
図19のコードC42のケース別のループそれぞれについて、アンロール数ceil(VL/n)だけアンローリング(展開)を行い、更に、アンローリングした命令のうち、先頭のベクトルストア命令の後のベクトルロード命令を、先頭のベクトル命令の前に移動するスケジューリングを行う。
【0081】
図20は、
図19のケース別ループに変換した分岐構造の中間擬似コードC42の各ケース別ループをそれぞれのアンロール数だけアンローリングした後の中間擬似コードC43を示す図である。
図20ではスケジューリングは未実行である。コードC43において、行09-37のケース2~8までのケース別ループでは、ベクトル演算命令がアンローリングされている。行09-19のケース2、3では、ケースの数(2、3)でそれぞれアンローリングされている。それに対して、行20-37のケース4、6、8では、宣言サイズnmがケースの数ceil(VL/n)=4, 6, 8以下であるので、アンロール数は宣言サイズnに制限される。行38-43のケース16は、ceil(VL/n)=16の例であり、配列サイズn=1であるので、ループの回転数m=n=1故、ベクトル化せず、元のコードC40 のスカラー命令のループ構造に戻される。そして、行44-50は、n>VLの条件を満たす場合であり、SFI_2が発生しないのでコードC41のループ構造のままである。
【0082】
[ループ内がストア命令の後にロード命令の例]
図21は、第2の実施の形態の最適化対象ループを有するソースコードとベクトル化後の中間擬似コードの例を示す図である。この例は、最内ループ(行04-07)内でストア命令のあとにロード命令がある例である。ソースコードC50では、配列変数a(n,33), b(n,33), c(n,33)の配列サイズnが変数であり、最内ループの回転数mが変数であり、そして、ベクトル長VLが定数または不明である。この場合、論理的にm=<nであり、n>VLのループを最適化対象ループから除くとすると、m=<VLが保証される。
【0083】
ソースコードC50の最内ループを回転数mでベクトル化すると、ベクトル化後の中間擬似コードC51が生成される。中間擬似コードC51では、C50の最内ループ(行04-07)が、以下の演算命令に変換されている。
do j = 1, m , VL //VL: 16
a(j: j+VL, i) = b(j: j+VL, i)
c(j: j+VL, i) = a(j: j+VL, i+1) + i
enddo
【0084】
ループ内がストア命令後ロード命令の場合も、コンパイラがSFI_2を回避する最適化処理は、ループ内がロード命令後ストア命令の場合(
図18、19,20)と同様に、(1)ベクトル化された中間擬似コードC51をケース別ループに変換し、各ループでアンローリングとスケジューリングを行う。但し、ループ内がストア命令後ロード命令であるので、アンローリング数がCeil(VL/n)-1となることが、ループ内がロード命令後ストア命令の場合と異なる。
【0085】
図22は、ベクトル化後の中間擬似コードC51の最内ループ(行03-07)をケース別ループに変換した分岐構造の中間擬似コードC52を示す図である。アンロール数以外は、
図19と同等であるので、
図22の説明は省略する。
【0086】
図23は、
図22のケース別ループに変換した分岐構造の中間擬似コードC52の各ケース別ループをそれぞれのアンロール数だけアンローリングした後の中間擬似コードC53を示す図である。アンローリング数がCeil(VL/n)-1となること以外は、
図20と同等であるので、
図23の説明は省略する。
【0087】
[第1及び第2の実施の形態のためのコンパイラの最適化処理]
次に、コンパイラの最適化処理についてフローチャートを参照して説明する。以下説明するコンパイラの最適化処理は、第1の実施の形態の最適化対象ループと第2の実施の形態の最適化対象ループの両方について行う最適化処理である。第1の実施の形態の最適化対象ループとは、ベクトル長VLと変数の配列サイズnが定数で、n<VLが真で、ループ内プログラムがSFI_2を発生する可能性があるループである。第2の実施の形態の最適化対象ループとは、ベクトル長VLと変数の配列サイズnが変数で、n<VLが不明で、ループ内プログラムがSFI_2を発生する可能性があるループである。
【0088】
図24は、コンパイラの最適化処理の全体のフローチャートを示す図である。コンパイラを実行するプロセッサは、ソースプログラムから生成した中間コード内の所定のループ構造を、一重ループ化(最内ループ消滅)またはアンパック化ストア命令及びロード命令で、SFI_2を回避できるように最適化する(S0)。
【0089】
そして、コンパイラを実行するプロセッサは、処理S0では最適化できないループについて、ループ構造を分析し、ループ毎のループ構造情報を格納したループ構造体を生成する(S1)。分析対象のループは、既にベクトル化されたストア命令及びロード命令を有するループである。
【0090】
図25は、ループ構造体の一例を示す図である。ループ構造体LOOP_STRUCTは、ループを最適化するために必要なループの特徴等を含むパラメータを格納したデータ構造である。ループ構造体は、最適化対象ループか否か(TRUE/FALSE)、ループタイプLoop_typeが1か2か、アンロール数、ベクトル長VLが不明(unknown)か否か、SFI_2が発生するか否か(TRUE/FALSE)、SFI_2のタイプSFI_2_typeが0か1か、SFI_2が発生するベクトル長VLの配列(VL_array)、などのパラメータを含む。
【0091】
ループタイプ1は、VL、nが定数で、n<VLが真のループであり、第1の実施の形態のループである。ループタイプ2は、VLが定数または不明、nが変数でn<VLが不明(unknown)のループであり、第2の実施の形態のループである。アンロール数は、ループタイプ1の場合はceil(VL/n) - SFI_2_type(0 or 1)であり、ループタイプ2の場合はNULLである。SFI_2のタイプSFI_2_typeは、ループ内がロード命令の後にストア命令の場合SFI_2_type=0であり、ループ内がストア命令の後にロード命令の場合SFI_2_type=1である。ループタイプ2は、ベクトル長VLが不明であるので、コンパイラを実行するプロセッサは、SFI_2が発生するベクトル長を調査し、発生することが検出されたベクトル長VLの値を、SFI_2が発生するベクトル長配列VL_arrayに格納する。
【0092】
図24に戻り、コンパイラを実行するプロセッサは、各ループのループ構造を分析し上記のループ構造体を生成する(S1)。そして、コンパイラを実行するプロセッサは、中間コードの各ループが最適化対象のループか否かを、ループ構造体を参照して判断する(S2)。プロセッサは、最適化対象ループ全てについて(S2のYES)、処理S3、S3-1、S3-2a、S3-2bを実行し、最適化対象ループが存在しない場合(S2のNO)は処理を終了する。
【0093】
コンパイラを実行するプロセッサは、最適化対象ループがタイプ1かタイプ2かをループ構造体に基づいて判定する(S3)。ループタイプLoop_type=1の場合、プロセッサは、ループを[Ceil(VL/n)-SFI_2_type]個だけアンローリングし(または[Ceil(VL/n)-SFI_2_type]>配列の宣言サイズn 、の場合はn個だけアンローリングし)、アンローリングした命令のうち、1回転目のベクトルストア命令の後ろのベクトルロード命令を1回転目のベクトルストア命令の前に移動(スケジューリング)する(S3-1)。移動させるベクトルロード命令は、[1-SFT_2_type]回転目以降のロード命令である。ループタイプ1の場合の上記処理S3-1は、
図11-12、
図16、
図18-20で説明した。
【0094】
一方、ループタイプ2の場合、コンパイラを実行するプロセッサは、ループをCeil(VL/n)別に分岐するケース別ループのプログラム(分岐プログラム)に変換する(S3-2a)。更に、プロセッサは、分岐プログラムのケース別ループをそれぞれ、[Ceil(VL/n)-SFI_2_type]個だけアンローリングする(または[Ceil(VL/n)-SFI_2_type]>配列の宣言サイズn、の場合はn個だけアンローリングする)。更に、プロセッサは、アンローリングした命令のうち、1回転目のベクトルストア命令の後ろのベクトルロード命令を1回転目のベクトルストア命令の前に移動(スケジューリング)する(S3-2b)。移動させるベクトルロード命令は、[2-SFT_2_type]回転目以降のロード命令である。ループタイプ2の場合の上記処理S3-2a,S3-2bは、
図14-15、
図17、
図21-23で説明した。
【0095】
図26は、ループ構造分析S1の処理のフローチャートを示す図である。コンパイラを実行するプロセッサは、中間コードのループが、2重以上のループ(多重ループ)、最内ループに1つの制御変数(j)を有し、最内ループに同じ配列変数(a)のベクトルストア命令とベクトルロード命令が1組だけ存在し、対象の配列変数(a)と同じ変数型で異なる配列サイズ(要素数n)の変数が存在しない、がすべてTRUEか否かを判定する(S11)。プロセッサは、判定結果がYESなら以下の処理を続行し、NOなら処理S1を終了する。
【0096】
コンパイラを実行するプロセッサは、最内ループで更新される配列変数のサイズと配列サイズ(n)を取得する(S12)。さらに、プロセッサは、ベクトルレジスタサイズ(byte数)を変数の型サイズ(byte数)で除算して、ベクトル長VLを算出する(S13)。配列サイズnが定数の場合ベクトル長VLが判明するが、配列サイズnが変数の場合ベクトル長VLは不明となる。
【0097】
更に、プロセッサは、n<VLが真か否か判定し、ceil(VL/n)を算出する(S14)。そして、プロセッサは、以下のループタイプの判定を行う。
S15:ベクトル長VLが定数、配列サイズnが定数、n<VLが真の場合は、ループタイプをタイプ1と判定する。
S16:ベクトル長VLが定数、配列サイズnが変数、n<VLが不明の場合は、ループタイプをタイプ2と判定する。
S17:ベクトル長VLが変数、配列サイズnが変数、n<VLが不明の場合は、ループタイプをタイプ2と判定する。
上記S15~S17が全てNOなら終了する。
ループタイプがタイプ1または2の場合は、プロセッサは、
図27以降のSFI_2の判定処理を実行する。
【0098】
図27、
図28は、SFI_2の判定処理S20のフローチャートを示す図である。コンパイラを実行するプロセッサは、ループがループタイプ1か2を判定し(S21)、ループタイプ1の場合は以下の処理S40,S22,S23,S23(2)を実行する。
【0099】
[ループタイプ1の場合]
コンパイラを実行するプロセッサは、連続するベクトルストア命令及びベクトルロード命令の関係を分析する(S40)。この分析で、ループがSFI_2を発生するか否かと(SFI_2=TRUE or FALSE)、ロード命令がストア命令の前か(SFI_2_type=0)後ろか(SFI_2_type=1)の判定を行う。詳細は
図29、
図30で行う。ループがSFI_2を発生する(SFI_2=TRUE)場合(S22のYES)、プロセッサは、ループ構造体に、SFI_2 = TRUEとSFI_2_type = 0 or 1を記録し、VL_arrayをNULLにする(S23)。VL_arrayをNULLにするのはベクトル長VLが定数で調査の必要性がないからである。ループがSFI_2を発生しない(SFI_2= FALSE)場合(S22のNO)、プロセッサは、ループ構造体に、SFI_2 = FALSEを記録する(S23(2))。
【0100】
[ループタイプ2の場合]
ループタイプ2の場合、コンパイラを実行するプロセッサは、ベクトル長VLが不明か否か判定する(S24)。不明でない場合(S24のFALSE)、プロセッサは、変数である配列サイズnを1からベクトル長VLまでインクリメントしながら、つまり、配列サイズnが1からベクトル長VLの値それぞれについて(S26)、以下の処理を実行する。つまり、プロセッサは、配列サイズn=VLに達してceil(VL/n)=1が真になる(S27のTRUE)と終了し(S27)、ceil(VL/n)=1が偽の場合(S27のFALSE)、連続するベクトルストア命令及びベクトルロード命令の関係を分析する(S40)。
【0101】
ループがSFI_2を発生する(SFI_2=TRUE)場合(S22のYES)、プロセッサは、ループ構造体に、SFI_2 = TRUEとSFI_2_type = 0 or 1を記録し、VL_arrayをNULLにする(S23)。そして、SFI_2の判定処理S20を終了する。ループがSFI_2を発生しない(SFI_2=FALSE)場合(S22のNO)、プロセッサは、全配列サイズnをチェックしてなければ(S33のNO)、S26に戻り配列サイズnをインクリメントする。全配列サイズnを終了していれば(S33のYES)、プロセッサは、ループ構造体にループがSFI_2を発生しない(SFI_2=FALSE)を記録し(S23(2))、終了する。つまり、配列サイズnを1からVLまでインクリメントしながら、一度でもSFI_2=TRUEを検出したら、そのループはSFI_2を発生する可能性があると判定する。
【0102】
図28に移り、ループタイプ2の場合で且つベクトル長VLが不明の場合(S24のTRUE)、プロセッサは、ベクトル長を2,4,8… と変更しながら、つまり取りうるベクトル長(2のべき乗)それぞれについて(S25)、処理S26~S30,S33を実行する。処理S26~S30のうち、S29とS30を除くS26, S27, S40, S28, S33は
図28と同じである。処理S29では、プロセッサは、ループ構造体に、SFI_2=TRUE、SFI_2_type = 0 or 1を保存し、ベクトル長配列VL_arrayに現在のVLを保存する。プロセッサは、全ベクトル長VLの判定が終了するまで上記の処理を繰り返す(S30)。つまり、全てのベクトル長VLそれぞれにおいて、配列サイズnを変更しながらSFI_2=TRUEを判定するまで処理S26, S27, S40, S28, S29, S33を繰り返す。これにより、プロセッサは、SFI_2が発生するベクトル長VLを全て検出し、ループ構造体内のクトル長配列VL_array内に検出したVLを全て登録する。
【0103】
プロセッサは、全ベクトル長VLに対する判定が終了したとき、ループ構造体のクトル長配列VL_array内が空の場合(S31のYES)、ループ構造体にSFI_2=FALSE、ループタイプ=NULLを記録する(S32)。この場合は、全VLでSFI_2が発生しないので、分析したループは最適化対象ループから除外される。
【0104】
[連続するベクトルストア命令及びベクトルロード命令の関係性の判定S40]
図29、
図30は、同じループ内及び前後のループ内のベクトルストア命令及びベクトルロード命令の関係性の判定処理S40のフローチャートを示す図である。コンパイラを実行するプロセッサは、同じループ内でロード命令の後ろにストア命令があるという順番か否かを判定する(S41)。判定が真の場合(S41のTRUE)、プロセッサは処理S42~S45を実行する。判定が偽の場合(S41のFALSE)、プロセッサは
図30の処理を実行する。
【0105】
S41の判定がTRUE(真)の場合、プロセッサは、第1に、ループ構造において、ループ間で前のループのベクトルストア命令vstore1と後ろのループのベクトルロード命令vload2の先頭の要素からベクトル長番目の要素までのアドレスが互いに重なるか否か判定する(S42)。この判定S42がFALSE(偽)であれば、SFI_1は発生せず、したがって、SFI_2も発生しないので、プロセッサはループ構造体にSFI_2はFALSEと記録する(S45)。S45のブロックの上に1回転目のベクトルストア命令vstore1と2回転目のベクトルロード命令vload1の関係が示される。
【0106】
判定S42がTRUE(真)の場合、プロセッサは、第2に、ループ構造において、ループ間で前のループのベクトルストア命令と後ろのループのベクトルロード命令がマスクに基づきアクセスする要素のアドレスが互いに重なるか否か判定する(S43)。この判定S43がFALSE(偽)であれば、SFI_2が発生する可能性があるので、プロセッサは、ループ構造体にSFI_2はTRUEと記録し、SFI_2_type = 0と記録する(S44)。判定S43がTRUE(真)であれば、SFI_1が発生し、したがって、SFI_2は発生しないので、プロセッサは、ループ構造体にSFI_2はFALSEと記録する(S46)。S44、S46のブロックの下に、1回転目のベクトルストア命令vstore1と2回転目のベクトルロード命令vload1の関係が示される。
【0107】
図30に示すとおり、S41の判定がFALSE(偽)の場合、プロセッサは、第1に、ループ構造において、ループ間の前のループのベクトルストア命令vstore1と同じ前のループ及び後ろのループのベクトルロード命令vload1, vload2の先頭の要素からベクトル長番目の要素までのアドレスが互いに重なるか否か判定する(S52)。つまり、同じループ内において前のベクトルストア命令vstore1と後ろのベクトルロード命令vload1との間で、先頭からベクトル長番目までの要素のアドレスが互いに重なるか否か判定する。この判定S52がFALSE(偽)であれば、SFI_1は発生せず、したがって、SFI_2も発生しないので、プロセッサはループ構造体にSFI_2はFALSEと記録する(S55)。S55のブロックの上に同じループ内の前のベクトルストア命令vstore1と後ろのベクトルロード命令vload1の関係が示される。
【0108】
判定S52がTRUE(真)の場合、プロセッサは、第2に、ループ構造において、ループ間の前のループのベクトルストア命令vstore1と同じ前のループ及び後ろのループのベクトルロード命令vload1, vload2がマスクに基づきアクセスする要素のアドレスが互いに重なるか否か判定する(S53)。つまり、同じループ内において前のベクトルストア命令vstore1と後ろのベクトルロード命令vload1との間で、両命令がマスクに基づきアクセスする要素のアドレスが互いに重なるか否か判定する。この判定がFALSE(偽)であれば、SFI_2が発生する可能性があるので、プロセッサは、ループ構造体にSFI_2はTRUEと記録し、SFI_2_type = 1と記録する(S54)。判定S53がTRUE(真)であれば、SFI_1が発生し、したがって、SFI_2は発生しないので、プロセッサは、ループ構造体にSFI_2はFALSEと記録する(S56)。S54、S56のブロックの下に、同じループ内の前のベクトルストア命令vstore1と後ろのベクトルロード命令vload1の関係が示される。
【0109】
以上の通り、プロセッサは、本実施の形態のコンパイラの最適化処理を実行し、アセンブリコードまたはオブジェクトコードを生成する。これにより、コンパイラを実行するプロセッサは、オブジェクトコードを実行するプロセッサが、ループ構造においてSFI_2が発生すると判定することを回避するように中間コードを最適化できる。また、プロセッサは、ループ構造において、配列サイズnが変数で、ベクトル長VLが不明の場合でも、プロセッサがオブジェクトコードを実行したときに判明する配列サイズnとベクトル長VLに対して、プロセッサがSFI_2と判定することを回避するよう中間コードを最適化できる。SFI_2と判定されることを回避できれば、プロセッサは、ロード命令をアウトオブオーダーで実行することができる。
【0110】
配列サイズnとループの回転数mが不一致m<nで連続アドレスへのアクセスでない場合、及び配列サイズnがベクトル長VLと所定の比率でない場合、コンパイラを実行するプロセッサは、SFI_2と判定されることを回避できるようにプログラムを最適化することができる。コンパイル時にベクトル長VLが定数または不明の場合や、配列サイズnが定数または変数の場合なども、コンパイラを実行するプロセッサは、コンパイル後のオブジェクトコードが実行されるときに判明した配列サイズnやベクトル長VLに対応してSFI_2と判定されることを回避できるようにプログラムを最適化できる。
【符号の説明】
【0111】
10:プロセッサ
12:メモリ
21:コンパイラ
22:パラメータ(ループ構造体)
23:ソースコード
24:中間コード
25:アセンブリコード(オブジェクトコード)
VL:ベクトル長
n:配列変数の配列サイズ
m:ループの回転数
SFI_1:一次SFI
SFI_2:二次SFI
vload:ベクトルロード命令
vstore:ベクトルストア命令
MASK:マスクレジスタ
Ceil():セイル関数、除算の余りを切り上げる関数
T:TRUE
F:FALSE