(19)【発行国】日本国特許庁(JP)
(12)【公報種別】公開特許公報(A)
(11)【公開番号】P2024030940
(43)【公開日】2024-03-07
(54)【発明の名称】ソースコード変換プログラムおよびソースコード変換方法
(51)【国際特許分類】
G06F 8/41 20180101AFI20240229BHJP
【FI】
G06F8/41 130
【審査請求】未請求
【請求項の数】4
【出願形態】OL
(21)【出願番号】P 2022134190
(22)【出願日】2022-08-25
(71)【出願人】
【識別番号】000005223
【氏名又は名称】富士通株式会社
(74)【代理人】
【識別番号】110002918
【氏名又は名称】弁理士法人扶桑国際特許事務所
(72)【発明者】
【氏名】ソアレス マウロ
(72)【発明者】
【氏名】松岡 秀樹
【テーマコード(参考)】
5B081
【Fターム(参考)】
5B081CC24
5B081CC32
(57)【要約】
【課題】コンパイル後のプログラムの実行性能を向上させる。
【解決手段】情報処理装置10は、配列データの中で変数nを含む第1のインデックスを用いて指定される要素を参照するコード15と、コード15の後に、配列データの中で第2のインデックスを用いて指定される要素を更新するコード16と、コード16の後に、配列データの中で第1のインデックスを用いて指定される要素を参照するコード17とを、ソースコード13から検出する。情報処理装置10は、コード16の前に、配列データの中で第1のインデックスを用いて指定される要素を変数varに代入するコード18を挿入し、コード17を、変数varを参照するコード19に置換する。
【選択図】
図1
【特許請求の範囲】
【請求項1】
配列データの中で第1の変数を含む第1のインデックスを用いて指定される要素を参照する第1のコードと、前記第1のコードの後に、前記配列データの中で前記第1のインデックスと異なる第2のインデックスを用いて指定される要素を更新する第2のコードと、前記第2のコードの後に、前記配列データの中で前記第1のインデックスを用いて指定される要素を参照する第3のコードとを、ソースコードから検出し、
前記第2のコードの前に、前記配列データの中で前記第1のインデックスを用いて指定される要素を第2の変数に代入する第4のコードを挿入し、前記第3のコードを、前記第2の変数を参照する第5のコードに置換する、
処理をコンピュータに実行させるソースコード変換プログラム。
【請求項2】
前記第4のコードは、前記第1のコードの前に挿入され、前記第3のコードの置換では更に、前記第1のコードを、前記第2の変数を参照する第6のコードに置換する、
請求項1記載のソースコード変換プログラム。
【請求項3】
前記第4のコードの挿入および前記第3のコードの置換によって前記ソースコードから変換される他のソースコードを生成し、コンパイラを用いて前記他のソースコードをコンパイルする処理を前記コンピュータに更に実行させる、
請求項1記載のソースコード変換プログラム。
【請求項4】
配列データの中で第1の変数を含む第1のインデックスを用いて指定される要素を参照する第1のコードと、前記第1のコードの後に、前記配列データの中で前記第1のインデックスと異なる第2のインデックスを用いて指定される要素を更新する第2のコードと、前記第2のコードの後に、前記配列データの中で前記第1のインデックスを用いて指定される要素を参照する第3のコードとを、ソースコードから検出し、
前記第2のコードの前に、前記配列データの中で前記第1のインデックスを用いて指定される要素を第2の変数に代入する第4のコードを挿入し、前記第3のコードを、前記第2の変数を参照する第5のコードに置換する、
処理をコンピュータが実行するソースコード変換方法。
【発明の詳細な説明】
【技術分野】
【0001】
本発明はソースコード変換プログラムおよびソースコード変換方法に関する。
【背景技術】
【0002】
コンパイラは、C言語などの高水準言語で記述されたソースコードから、機械語などの低水準言語で記述されたオブジェクトコードを生成する。このとき、コンパイラは、ソースコードに規定された処理の意味が変わらない範囲で、実行時間が短くなるように命令を最適化するコンパイラ最適化を行うことがある。
【0003】
典型的なコンパイラは、ソースコードの細かな記載の違いに依存しないように最適化アルゴリズムを規定するため、ソースコードよりも低レベルな中間コードに対してコンパイラ最適化を実行する。例えば、コンパイラは、ソースコードに対して字句解析や構文解析を行って、コンパイラ内部で使用される中間コードを生成する。コンパイラは、中間コードに対して最適化アルゴリズムを実行して、中間コードを書き換える。コンパイラは、書き換えられた中間コードをオブジェクトコードに変換する。
【0004】
なお、特定のパターンに合致する命令を含む部分プログラムを検出し、検出された部分プログラムに含まれる他の命令の依存関係を当該パターンと整合するように修正するコンパイラが提案されている。また、中間コードの中から配列参照を検出し、2回以上参照されている配列についてメモリアクセスをバッファアクセスに変換するコンパイラが提案されている。また、配列に対する複数回のアクセスの依存関係を解析し、配列アクセスをシフトレジスタへのアクセスに置換する設計装置が提案されている。
【先行技術文献】
【特許文献】
【0005】
【特許文献1】特開2005-339021号公報
【特許文献2】特開2007-272672号公報
【特許文献3】特開2014-225200号公報
【発明の概要】
【発明が解決しようとする課題】
【0006】
ソースコードは、複数の要素を並べた配列データを扱うことがある。ソースコードにおいて、配列データに含まれる要素の参照や更新は、配列名と要素の位置を示すインデックスとを用いて記述されることがある。あるソースコードは、配列データの中の要素を参照し、その後に当該配列データの中の要素を更新し、その後に当該配列データの中の要素を再び参照するという処理を規定する可能性がある。このとき、コンパイラは、更新される要素と2回目に参照される要素とが同一でないと判断できれば、無駄なロード命令を減らすなどのコンパイラ最適化を実行し得る。
【0007】
しかし、インデックスが、変数を用いて規定されていることがある。例えば、インデックスが、数値変数を含む式として規定されていることがある。その場合、コンパイラは、中間コードレベルの情報のみでは、更新される要素と2回目に参照される要素との同一性を判断することが難しいことがある。その結果、コンパイラは、更新とその後の参照との間に依存関係があるというRAW(Read After Write)のケースに該当する可能性があると判断し、コンパイラ最適化を断念するおそれがある。
【0008】
例えば、中間コードは、変数の値からインデックスの具体的な値をオフセットとして算出し、配列データの先頭アドレスにオフセットを加算して要素のアドレスを算出し、そのアドレスを用いてメモリからデータをロードするといった、低レベルの処理を規定する。そのため、中間コードレベルでは、コンパイラは、インデックスを用いた複数回の配列アクセスを大局的に解析することが難しいことがある。その結果、コンパイラは、実行性能が高くないプログラムを出力する可能性がある。そこで、1つの側面では、本発明は、コンパイル後のプログラムの実行性能を向上させることを目的とする。
【課題を解決するための手段】
【0009】
1つの態様では、以下の処理をコンピュータに実行させるソースコード変換プログラムが提供される。配列データの中で第1の変数を含む第1のインデックスを用いて指定される要素を参照する第1のコードと、第1のコードの後に、配列データの中で第1のインデックスと異なる第2のインデックスを用いて指定される要素を更新する第2のコードと、第2のコードの後に、配列データの中で第1のインデックスを用いて指定される要素を参照する第3のコードとを、ソースコードから検出する。第2のコードの前に、配列データの中で第1のインデックスを用いて指定される要素を第2の変数に代入する第4のコードを挿入し、第3のコードを、第2の変数を参照する第5のコードに置換する。
【0010】
また、1つの態様では、コンピュータが実行するソースコード変換方法が提供される。
【発明の効果】
【0011】
1つの側面では、コンパイル後のプログラムの実行性能が向上する。
【図面の簡単な説明】
【0012】
【
図1】第1の実施の形態の情報処理装置を説明するための図である。
【
図2】第2の実施の形態の情報処理装置のハードウェア例を示す図である。
【
図4】情報処理装置の機能例を示すブロック図である。
【
図5】オリジナルのソースコードの例を示す図である。
【
図9】最適化されたスケジュールテーブルの例を示す図である。
【
図10】オリジナルのソースコードの他の例を示す図である。
【
図12】変換後のソースコードの他の例を示す図である。
【
図13】コンパイルの手順例を示すフローチャートである。
【
図14】コンパイルの手順例を示すフローチャート(続き1)である。
【
図15】コンパイルの手順例を示すフローチャート(続き2)である。
【発明を実施するための形態】
【0013】
以下、本実施の形態を図面を参照して説明する。
[第1の実施の形態]
第1の実施の形態を説明する。
【0014】
図1は、第1の実施の形態の情報処理装置を説明するための図である。
第1の実施の形態の情報処理装置10は、ソースコード13のコンパイル前に、コンパイラ最適化が適切に行われるようにソースコード13を変換する。ソースコード13を変換するハードウェアまたはソフトウェアが、プリプロセッサまたはプリコンパイラと呼ばれてもよい。コンパイルは、情報処理装置10によって実行されてもよいし、他の情報処理装置によって実行されてもよい。情報処理装置10は、ソースコード13をソースコード14に変換してもよく、ソースコード14をコンパイラに入力してもよい。また、情報処理装置10は、ソースコード14を明示的に出力しなくてもよく、以下のコード変換処理に続けて、中間コード生成およびコンパイラ最適化に進んでもよい。情報処理装置10は、クライアント装置でもよいしサーバ装置でもよい。情報処理装置10が、コンピュータまたはソースコード変換装置と呼ばれてもよい。
【0015】
情報処理装置10は、記憶部11および処理部12を有する。記憶部11は、RAM(Random Access Memory)などの揮発性半導体メモリでもよいし、HDD(Hard Disk Drive)やフラッシュメモリなどの不揮発性ストレージでもよい。処理部12は、例えば、CPU(Central Processing Unit)、GPU(Graphics Processing Unit)、DSP(Digital Signal Processor)などのプロセッサである。ただし、処理部12が、ASIC(Application Specific Integrated Circuit)やFPGA(Field Programmable Gate Array)などの電子回路を含んでもよい。プロセッサは、例えば、RAMなどのメモリ(記憶部11でもよい)に記憶されたプログラムを実行する。プロセッサの集合が、マルチプロセッサまたは単に「プロセッサ」と呼ばれてもよい。
【0016】
記憶部11は、ソースコード13を記憶する。ソースコード13は、C言語などの高水準言語で記述されたプログラムである。ソースコード13は、複数の要素を並べた配列データの参照および更新を含む処理を規定する。要素はレコードと呼ばれてもよく、複数の要素は同じデータ型のデータであってもよい。
【0017】
ソースコード13は、コード15,16,17を含む。コード16の実行順序はコード15の後であり、コード17の実行順序はコード16の後である。コード15,16,17は、命令、部分プログラム、文字列、文または式と呼ばれてもよい。コード15は、配列データの中で、変数nを含む第1のインデックスを用いて指定される要素を参照する。変数nは、例えば、整数変数などの数値変数である。コード15は、例えば、配列名Aと、変数nを含むインデックス式(例えば、n+1)とを含む。配列名は、例えば、配列データの先頭アドレスを指し示すポインタに相当する。インデックスは、例えば、配列データの先頭からの相対位置を示すオフセットに相当する。参照は、読み出し(Read)と呼ばれてもよい。要素の参照は、例えば、等号の右辺に記載される。
【0018】
コード16は、コード15と同じ配列データの中で、コード15と異なる第2のインデックスを用いて指定される要素を更新する。第2のインデックスは、変数nを含んでもよいし含まなくてもよい。コード16は、例えば、配列名Aと、変数nを含むインデックス式(例えば、n+0)とを含む。更新は、書き込み(Write)と呼ばれてもよい。要素の更新は、例えば、等号の左辺に記載される。
【0019】
コード17は、コード15,16と同じ配列データの中で、コード15と同じ第1のインデックスを用いて指定される要素を参照する。コード17は、例えば、配列名Aと、変数nを含むインデックス式(例えば、n+1)とを含む。コード15とコード17の間では、変数nの値が更新されていないことが好ましい。また、コード15とコード17の間では、第1のインデックスを用いた更新が行われていないことが好ましい。
【0020】
処理部12は、ソースコード13を解析して書き換える。処理部12は、ソースコード13に対して構文解析を行って抽象構文木(AST:Abstract Syntax Tree)を生成してもよく、抽象構文木に対して以下の検出処理および書き換え処理を実行してもよい。また、処理部12は、ソースコード13からソースコード14を生成してもよい。処理部12は、書き換えられた抽象構文木からソースコード14を生成してもよい。生成されたソースコード14は、例えば、記憶部11に記憶される。
【0021】
処理部12は、ソースコード13から、上記の条件を満たすコード15,16,17を検出する。すると、処理部12は、実行順序がコード16の前になるようにコード18を挿入する。処理部12は、実行順序がコード15の前になるようにコード18を挿入してもよい。コード18は、コード15,16,17と同じ配列データの中で、コード15,17と同じ第1のインデックスを用いて指定される要素を、変数varに代入する。例えば、変数varが等号の左辺に記載され、指定の要素が等号の右辺に記載される。変数varは、例えば、ソースコード13に出現しない新たな一時変数(テンポラル変数)である。変数varのデータ型は、例えば、配列データの各要素のデータ型と同じである。
【0022】
また、処理部12は、第1のインデックスを含むコード17を、変数varを参照するコード19に置換する。例えば、変数varが等号の右辺に記載される。処理部12は更に、第1のインデックスを含むコード15を、変数varを参照するコードに置換してもよい。これにより、ソースコード13がソースコード14に変換される。
【0023】
ソースコード14は、コード16,18,19を含む。また、ソースコード14は、コード15またはコード15から変換されたコードを含む。中間コード生成およびコンパイラ最適化は、ソースコード13に代えてソースコード14に対して行われる。処理部12は、ソースコード14を出力してもよい。処理部12は、ソースコード14を表示装置に表示してもよいし、他の情報処理装置に送信してもよい。
【0024】
以上説明したように、第1の実施の形態の情報処理装置10は、変数nを含む第1のインデックスで指定される要素を参照するコード15を、ソースコード13から検出する。また、情報処理装置10は、第2のインデックスで指定される要素を更新するコード16と、第1のインデックスで指定される要素を参照するコード17とを、ソースコード13から検出する。情報処理装置10は、少なくともコード16の前に、第1のインデックスを用いて指定される要素を変数varに代入するコード18を挿入し、コード17を、変数varを参照するコード19に置換する。
【0025】
中間コードは、ソースコードよりも低レベルの処理を規定しており、配列データの要素を指定するインデックスの同一性についてソースコードよりも少ない情報しかもたないことがある。また、1回に最適化対象となるコード範囲には限りがある。そのため、中間コードに対するコンパイラ最適化において、コンパイラは、複数回の配列アクセスを大局的に解析して参照と更新の依存関係を正確に判断することが難しいことがある。
【0026】
この点、ソースコード13をコンパイルする場合、コンパイラは、指定される要素が変数nの値に依存するため、中間コードレベルの情報のみでは、コード16で更新される要素とコード17で参照される要素とが同一でないと断定することが難しいことがある。このため、コンパイラは、更新とその後の参照との間に依存関係があるというRAWのケースに該当する可能性があると判断し、ソースコード13に規定された処理の意味を変えてしまう可能性があるため、コンパイラ最適化を断念することがある。なお、更新とその後の参照との間に依存関係が無いことが、無相関と呼ばれてもよい。
【0027】
その結果、コンパイラは、コード15と同じデータをコード17でメモリからレジスタにロードし直すようなオブジェクトコードや、コード16とコード17とを並列化しないオブジェクトコードなどを出力する可能性がある。よって、コンパイラは、実行性能が高くないオブジェクトコードを出力する可能性がある。
【0028】
これに対して、ソースコード14をコンパイルする場合、コンパイラは、中間コードレベルの情報のみからでも、コード18で変数varに代入された値とコード19で参照される変数varの値とが同一であることを容易に確認できる。また、コード16で更新される配列データの要素とコード19で参照される変数varの値とは、明らかに異なるデータである。このため、コンパイラは、RAWのケースに該当する可能性を検討しなくてよく、コンパイラ最適化を実行することができる。
【0029】
その結果、コンパイラは、ソースコード13の場合よりロード命令が少ないオブジェクトコードや、パイプラインストールによる待ち時間が少ないオブジェクトコードや、コード16とコード17とを並列化したオブジェクトコードなどを出力し得る。よって、コンパイラは、実行性能が高いオブジェクトコードを出力する。
【0030】
なお、情報処理装置10は、コード18をコード15の前に挿入してもよく、コード15を変数varを参照するコードに置換してもよい。これにより、コンパイラは、ロード命令の少ないオブジェクトコードを出力し得る。また、情報処理装置10は、ソースコード13から変換されたソースコード14を生成してもよく、コンパイラを用いてソースコード14をコンパイルしてもよい。これにより、既存のコンパイラを利用して、ソースコード13に対応するオブジェクトコードが円滑に生成される。
【0031】
[第2の実施の形態]
次に、第2の実施の形態を説明する。
第2の実施の形態の情報処理装置100は、C言語などの高水準言語で記述されたソースコードをコンパイルして、機械可読な実行コードを生成する。ただし、後述するプリプロセッサとコンパイラとリンカとが、異なる情報処理装置によって実行されてもよい。情報処理装置100は、クライアント装置でもよいしサーバ装置でもよい。情報処理装置10が、コンピュータまたはコンパイル装置と呼ばれてもよい。なお、情報処理装置100は、第1の実施の形態の情報処理装置10に対応する。
【0032】
図2は、第2の実施の形態の情報処理装置のハードウェア例を示す図である。
情報処理装置100は、バスに接続されたCPU101、RAM102、HDD103、GPU104、入力インタフェース105、媒体リーダ106および通信インタフェース107を有する。CPU101は、第1の実施の形態の処理部12に対応する。RAM102またはHDD103は、第1の実施の形態の記憶部11に対応する。
【0033】
CPU101は、プログラムの命令を実行するプロセッサである。CPU101は、HDD103に記憶されたプログラムおよびデータをRAM102にロードし、プログラムを実行する。情報処理装置100は、複数のプロセッサを有してもよい。
【0034】
RAM102は、CPU101で実行されるプログラムおよびCPU101で演算に使用されるデータを一時的に記憶する揮発性半導体メモリである。情報処理装置100は、RAM以外の種類の揮発性メモリを有してもよい。なお、RAM102は、バスに接続されたRAMインタフェースに挿入されてもよい。また、バスに接続されたDMA(Direct Memory Access)コントローラが、CPU101を介さずにRAM102と周辺機器との間でデータを直接転送してもよい。
【0035】
HDD103は、オペレーティングシステム(OS:Operating System)やミドルウェアやアプリケーションソフトウェアなどのソフトウェアのプログラムと、データとを記憶する不揮発性ストレージである。情報処理装置100は、フラッシュメモリやSSD(Solid State Drive)などの他の種類の不揮発性ストレージを有してもよい。
【0036】
GPU104は、CPU101と連携して画像処理を行い、情報処理装置100に接続された表示装置111に画像を出力する。表示装置111は、例えば、CRT(Cathode Ray Tube)ディスプレイ、液晶ディスプレイ、有機EL(Electro Luminescence)ディスプレイまたはプロジェクタである。情報処理装置100に、プリンタなどの他の種類の出力デバイスが接続されてもよい。また、GPU104は、GPGPU(General Purpose Computing on Graphics Processing Unit)として使用されてもよい。GPU104は、CPU101からの指示に応じてプログラムを実行し得る。情報処理装置100は、RAM102以外の揮発性半導体メモリをGPUメモリとして有してもよい。
【0037】
入力インタフェース105は、情報処理装置100に接続された入力デバイス112から入力信号を受け付ける。入力デバイス112は、例えば、マウス、タッチパネルまたはキーボードである。情報処理装置100に複数の入力デバイスが接続されてもよい。
【0038】
媒体リーダ106は、記録媒体113に記録されたプログラムおよびデータを読み取る読み取り装置である。記録媒体113は、例えば、磁気ディスク、光ディスクまたは半導体メモリである。磁気ディスクには、フレキシブルディスク(FD:Flexible Disk)およびHDDが含まれる。光ディスクには、CD(Compact Disc)およびDVD(Digital Versatile Disc)が含まれる。媒体リーダ106は、記録媒体113から読み取られたプログラムおよびデータを、RAM102やHDD103などの他の記録媒体にコピーする。読み取られたプログラムは、CPU101によって実行されることがある。
【0039】
記録媒体113は、可搬型記録媒体であってもよい。記録媒体113は、プログラムおよびデータの配布に用いられることがある。また、記録媒体113およびHDD103が、コンピュータ読み取り可能な記録媒体と呼ばれてもよい。
【0040】
通信インタフェース107は、ネットワーク114を介して他の情報処理装置と通信する。通信インタフェース107は、スイッチやルータなどの有線通信装置に接続される有線通信インタフェースでもよいし、基地局やアクセスポイントなどの無線通信装置に接続される無線通信インタフェースでもよい。
【0041】
図3は、CPUの構造例を示すブロック図である。
コンパイラがターゲットとするCPU、すなわち、情報処理装置100が生成する実行コードを実行するCPUは、CPUコア121,122およびL2キャッシュメモリ123を有する。ターゲットCPUは、情報処理装置100が有するCPU101でもよい。
【0042】
CPUコア121は、ロードストアユニット124,125を含む複数のロードストアユニット、整数ユニット126を含む複数の整数ユニット、浮動小数点ユニット127を含む複数の浮動小数点ユニット、および、L1キャッシュメモリ128を有する。CPUコア122は、CPUコア121と同様のハードウェアを有する。ターゲットCPUが、3以上のCPUコアを有していてもよい。
【0043】
CPUコア121,122は、機械語の命令を並列に実行する。ロードストアユニット124,125は、RAMからレジスタにデータを読み出すロード命令と、レジスタからRAMにデータを書き込むストア命令とを実行する演算回路である。ロードストアユニット124,125は、互いに並列に命令を実行できる。以下の説明では、ロードストアユニット124をLSU(Load Store Unit)0と呼ぶことがあり、ロードストアユニット125をLSU1と呼ぶことがある。ロード命令の実行には3サイクルを要し、ストア命令の実行には1サイクルを要する。
【0044】
整数ユニット126は、整数データに対する加算命令や減算命令など、整数演算命令を実行する演算回路である。整数ユニット126は、ロードストアユニット124,125と並列に命令を実行できる。以下の説明では、整数ユニット126をALU(Arithmetic and Logic Unit)と呼ぶことがある。整数演算命令の実行には、1サイクルを要する。
【0045】
浮動小数点ユニット127は、浮動小数点データに対する加算命令や減算命令など、浮動小数点演算命令を実行する演算回路である。浮動小数点ユニット127は、ロードストアユニット124,125や整数ユニット126と並列に命令を実行できる。浮動小数点ユニット127は、FPU(Floating Point Unit)と呼ばれることがある。浮動小数点演算命令の実行には、3サイクルを要する。
【0046】
CPUコア121は、命令パイプラインを有していてもよい。命令パイプラインは、命令フェッチ、命令デコード、実行、メモリアクセス、ライトバックなどの複数のステージを含む。各命令は、これら複数のステージを一定の順序で進む。異なるステージの回路は、異なる命令を並列に処理することができる。あるステージの回路がある命令を処理しているとき、1つ前のステージの回路は次の命令を処理することができる。
【0047】
ただし、依存関係がある命令は、命令パイプラインに連続的に投入することができず、命令パイプラインの一部のステージが待機状態になるパイプラインハザードが発生することがある。パイプラインハザードは、ストールと呼ばれることがある。ストールが多く発生すると、実行コードの実行効率が低下する。命令間の依存関係として、ある命令の演算結果を次の命令が利用するというデータ依存関係がある。データ依存関係によって生じるパイプラインハザードは、データハザードと呼ばれることがある。
【0048】
L1キャッシュメモリ128は、ロードストアユニット124,125、整数ユニット126、浮動小数点ユニット127などの複数の演算回路によって使用される揮発性メモリである。L1キャッシュメモリ128は、演算回路に最も近いレベル1のキャッシュメモリである。L1キャッシュメモリ128は、演算回路から要求される命令やデータを、L2キャッシュメモリ123から読み出して一時的に記憶する。
【0049】
L2キャッシュメモリ123は、CPUコア121,122によって使用される揮発性メモリである。L2キャッシュメモリ123は、L1キャッシュメモリ128よりも演算回路から遠いレベル2のキャッシュメモリである。ただし、L2キャッシュメモリ123に相当するキャッシュメモリが、L3キャッシュメモリまたはLLC(Last Level Cache)と呼ばれることがある。L2キャッシュメモリ123は、CPUコア121,122から要求される命令やデータを、RAMから読み出して一時的に記憶する。
【0050】
図4は、情報処理装置の機能例を示すブロック図である。
情報処理装置100は、ソースコード記憶部131,132、実行コード記憶部133、プリプロセッサ134、コンパイラ137およびリンカ138を有する。ソースコード記憶部131,132および実行コード記憶部133は、例えば、RAM102またはHDD103を用いて実装される。プリプロセッサ134、コンパイラ137およびリンカ138は、例えば、CPU101およびプログラムを用いて実装される。
【0051】
ソースコード記憶部131は、ユーザが作成したオリジナルのソースコードを記憶する。ソースコードは、例えば、C言語で記述されている。ソースコード記憶部132は、プリプロセッサ134によって変換されたソースコードを記憶する。変換後のソースコードは、オリジナルのソースコードと同じプログラミング言語で記述されている。実行コード記憶部133は、ターゲットCPUで実行可能な実行コードを記憶する。実行コードは、例えば、機械語で記述されている。ただし、ミドルウェアを介して実行コードを実行する場合、機械語よりも高レベルな言語で実行コードが記述されていてもよい。
【0052】
プリプロセッサ134は、ソースコードをコンパイルする前に、ソースコードに規定された処理の意味が変わらない範囲で、コンパイラ最適化に適した表現にソースコードを変換する。プリプロセッサ134は、プリコンパイラと呼ばれることがある。プリプロセッサ134は、解析部135および書き換え部136を有する。
【0053】
解析部135は、ソースコード記憶部131に記憶されたオリジナルのソースコードに対して字句解析および構文解析を行い、抽象構文木を生成する。解析部135は、抽象構文木を解析して、一定条件を満たす書き換え範囲を検出する。ただし、解析部135は、抽象構文木を生成せずにソースコードを直接解析してもよい。
【0054】
書き換え部136は、解析部135によって検出された書き換え範囲に対して、一定の書き換え規則を適用し、抽象構文木の少なくとも一部分を書き換える。書き換え部136は、書き換えられた抽象構文木をソースコードに変換し、変換されたソースコードをソースコード記憶部132に保存する。ただし、書き換え部136は、抽象構文木を書き換えずにソースコードを直接書き換えてもよい。なお、プリプロセッサ134は、変換後のソースコードを表示装置111に表示してもよく、他の情報処理装置に送信してもよい。
【0055】
コンパイラ137は、ソースコード記憶部132に記憶された変換後のソースコードをコンパイルする。コンパイラ137は、ソースコードに対して字句解析、構文解析および意味解析を行って中間コードを生成する。コンパイラ137は、コンパイラ最適化として、中間コードに対して最適化アルゴリズムを適用して中間コードを書き換える。コンパイラ137は、中間コードをオブジェクトコードに変換して出力する。オブジェクトコードは、例えば、機械語で記述されている。
【0056】
リンカ138は、コンパイラ137が出力するオブジェクトコードと、他のモジュールのオブジェクトコードやライブラリプログラムとをリンクして、実行コードを生成する。リンカ138は、生成した実行コードを実行コード記憶部133に保存する。
【0057】
次に、配列アクセスに関するコンパイラ最適化について説明する。
図5は、オリジナルのソースコードの例を示す図である。
ソースコード141は、ソースコード記憶部131に記憶される。ソースコード141には、関数ex1が記載されている。関数ex1は、変数n,Aによって表される2つの引数を受け付ける。変数nは、インデックスに用いられる整数である。変数Aは、文字型の配列の先頭アドレスを示すポインタである。変数Aは、配列名に相当する。
【0058】
配列名とインデックスの組は、配列に含まれる複数の要素のうち、インデックスによって指定される要素にアクセスする配列アクセスを表す。配列アクセスは、変数Aが示す先頭アドレスに、変数nを含むインデックスが示すオフセットを加えて要素アドレスを算出し、要素アドレスが指し示すデータにアクセスすることに相当する。等号の左辺の配列アクセスは、要素を更新する書き込み(Write)を表す。等号の右辺の配列アクセスは、要素を参照する読み出し(Read)を表す。
【0059】
ソースコード141の第3行は、配列Aのn+1番目の要素と配列Aのn-1番目の要素を読み出し、2つの要素の和を配列Aのn+0番目に書き込む処理を規定する。ソースコード141の第4行は、配列Aのn+1番目の要素と配列Aのn-1番目の要素を読み出し、2つの要素の和を配列Aのn+1番目に書き込む処理を規定する。
【0060】
図6は、中間コードの例を示す図である。
コンパイラ137がソースコード141をそのままコンパイルすると、コンパイラ137は中間コード142を生成する。中間コード142には、コード142aに示すように、第3行および第4行の配列アクセスが低レベルの処理として規定される。
【0061】
ソースコード141の配列アクセスには、変数nを含む式がインデックスとして使用されている。このため、中間コード142には、変数nの値からインデックスの値をオフセットとして算出し、配列Aの先頭アドレスにオフセットを加えて要素アドレスを算出し、要素アドレスを用いてメモリにアクセスするといった処理が規定される。配列アクセスが低レベルのレジスタ演算やメモリアクセスとして表現されるため、中間コード142は、配列アクセスに関して、ソースコード141より少ない情報しかもたないことがある。
【0062】
ここで、ソースコード141を見ると、第3行の右辺は、要素A[n+1],A[n-1]の読み出しを規定している。第3行の左辺は、要素A[n+0]の書き込みを規定している。第4行の右辺は、要素A[n+1],A[n-1]の読み出しを規定している。要素A[n+1],A[n-1]の2回の読み出しの間に、要素A[n+1],A[n-1]の書き込みは行われておらず、変数nの値も更新されていない。また、2回の読み出しの間で行われる要素A[n+0]の書き込みは、要素A[n+1],A[n-1]の値に影響を与えない。このため、2回の読み出しで読み出される値は同一である。
【0063】
そこで、コンパイラ137は、第3行で読み出される要素A[n+1],A[n-1]を保存しておき、第4行の要素A[n+1],A[n-1]の読み出しを省略するようなオブジェクトコードを生成することができるようにも思われる。しかし、中間コード142には、ソースコード141と異なり、変数nを含む式として表現されたインデックスの情報が欠けている。また、コンパイラ最適化は、一定幅のウィンドウサイズに含まれる命令群の単位で最適化アルゴリズムを実行する。
【0064】
このため、中間コードレベルでコンパイラ最適化を行うコンパイラ137は、上記のように複数回の配列アクセスを大局的に解析して最適化することが難しい。コンパイラ137は、第3行の左辺で書き込まれる要素と第4行の右辺で読み出される要素が同一でないとは断定できず、RAWに該当する可能性があると判断する。その結果、コンパイラ137は、処理の意味が変わらないように、コンパイラ最適化を断念することがある。
【0065】
図7は、スケジュールテーブルの例を示す図である。
ソースコード141をそのままコンパイルした場合、コンパイラ137は、スケジュールテーブル143に示すようなオブジェクトコードを生成することがある。スケジュールテーブル143において、w0,w2,w4,w5は32ビットレジスタであり、x1,x2,x3は64ビットレジスタである。関数ex1の呼び出し時点で、配列Aのポインタはレジスタx1に記憶されており、変数nの値はレジスタw0に記憶されている。sxtwは、ビット数を変換する命令である。ldrbは、8ビットロード命令である。strbは、8ビットストア命令である。命令ldrb,strbは、[ベースアドレス,オフセット]によってメモリアドレスを指定する。
【0066】
第1サイクルにおいて、ALUは変数nの値のビット変換を行う。第2サイクルにおいて、ALUはn+1を算出する。第3サイクルにおいて、ALUはn-1を算出する。第4サイクルにおいて、LSU0はメモリからA[n+1]を読み出し、LSU1はメモリからA[n-1]を読み出す。第5サイクルおよび第6サイクルは、LSU0,LSU1のロード命令の完了待ちであり、ストールに相当する。
【0067】
第7サイクルにおいて、ALUはA[n+1]+A[n-1]を算出する。第8サイクルにおいて、LSU0はメモリからA[n+1]を読み出し、LSU1はメモリにA[n+0]=A[n+1]+A[n-1]を書き込む。第9サイクルにおいて、LSU1はメモリからA[n-1]を読み出す。第10サイクルおよび第11サイクルは、LSU0,LSU1のロード命令の完了待ちであり、ストールに相当する。
【0068】
第12サイクルにおいて、ALUはA[n+1]+A[n-1]を算出する。第13サイクルにおいて、LSU1はメモリにA[n+1]=A[n+1]+A[n-1]を書き込む。第14サイクルにおいて、ALUは関数ex1の呼び出し元に復帰する。
【0069】
このように、コンパイラ137は、A[n+0]の書き込みとその後のA[n+1],A[n-1]の読み出しとが無相関であることを判断できず、安全性の観点から、A[n+1],A[n-1]を再度読み出している。その結果、ロード命令が増加してストールが増えている。そこで、プリプロセッサ134は、コンパイラ137がRAWの可能性を検討しなくて済むように、コンパイル前にソースコード141を変換する。
【0070】
図8は、変換後のソースコードの例を示す図である。
ソースコード144は、ソースコード141から変換されてソースコード記憶部132に記憶される。ソースコード144の第3行は、配列Aの要素と同じデータ型である文字型の変数temp_1,temp_2を宣言している。変数temp_1,temp_2は、ソースコード141には含まれない新たな一時変数である。
【0071】
ソースコード144の第4行は、配列Aのn+1番目の要素を読み出して変数temp_1に代入する処理を規定する。ソースコード144の第5行は、配列Aのn-1番目の要素を読み出して変数temp_2に代入する処理を規定する。ソースコード144の第6行は、変数temp_1,temp_2の値の和を配列Aのn+0番目に書き込む処理を規定する。ソースコード144の第7行は、変数temp_1,temp_2の値の和を配列Aのn+1番目に書き込む処理を規定する。
【0072】
ソースコード144では、RAWに該当するか否か検討を要するような配列アクセスが解消されている。このため、コンパイラ137は、同一要素の2回目の読み出しを省略してストールを減らすコンパイラ最適化を行うことができる。
【0073】
図9は、最適化されたスケジュールテーブルの例を示す図である。
ソースコード144をコンパイルした場合、コンパイラ137は、スケジュールテーブル145に示すようなオブジェクトコードを生成することがある。第1サイクルにおいて、ALUは変数nの値のビット変換を行う。第2サイクルにおいて、ALUはn+1を算出する。第3サイクルにおいて、ALUはA[n+0]のアドレスを算出する。
【0074】
第4サイクルにおいて、LSU0はメモリからA[n+1]を読み出し、LSU1はメモリからA[n-1]を読み出す。第5サイクルおよび第6サイクルは、LSU0,LSU1のロード命令の完了待ちであり、ストールに相当する。第7サイクルにおいて、ALUはA[n+1]+A[n-1]を算出する。第8サイクルにおいて、ALUはA[n+1]+A[n-1]の下位8ビットを抽出する。
【0075】
第9サイクルにおいて、LSU0はメモリにA[n+1]=A[n+1]+A[n-1]を書き込み、LSU1はメモリにA[n+0]=A[n+1]+A[n-1]を書き込む。第10サイクルにおいて、ALUは関数ex1の呼び出し元に復帰する。このように、コンパイラ137は、ソースコード144からは、ソースコード141よりも4サイクル少ないオブジェクトコードを生成する。また、ストールが2サイクル減少している。
【0076】
次に、プリプロセッサ134のソースコード変換方法について説明する。
プリプロセッサ134は、ソースコードから配列名とインデックスの組による配列アクセスを抽出する。プリプロセッサ134は、配列アクセスを配列要素の読み出しと配列要素の書き込みとに区別し、読み出しを読み出しリストに記録し、書き込みを書き込みリストに記録する。このとき、プリプロセッサ134は、配列名とインデックスの組毎に分類して、ソースコード上での読み出し位置および書き込み位置を記録する。また、プリプロセッサ134は、インデックスに含まれる変数の値の更新も書き込みリストに記録する。インデックスに含まれる変数を、以下ではインデックス変数と呼ぶことがある。
【0077】
プリプロセッサ134は、読み出しリストに含まれる配列名とインデックスの組毎に、ソースコード上での1以上の書き換え範囲候補を判定する。書き換え範囲候補の先頭は、最初の読み出し位置である。書き換え範囲候補の末尾は、最後の読み出し位置である。ただし、最初の読み出し位置と最後の読み出し位置との間に、同じインデックスによる書き込みまたはインデックス変数の更新がある場合、書き換え範囲候補の末尾は、次の書き込み位置である。ある書き換え範囲候補の末尾が最後の読み出し位置でない場合、次の書き換え範囲候補の先頭は、末尾となった書き込み位置の次の読み出し位置である。
【0078】
プリプロセッサ134は、上記で判定された書き換え範囲候補のうち、複数回の読み出しがあり、かつ、読み出し間に別インデックスによる同一配列の書き込みがある書き換え範囲候補を、書き換え範囲として採用する。書き換え範囲は、書き込みとその後の読み出しとの間に依存関係があるRAWには該当しないものの、コンパイラ137が誤ってRAWに該当すると判断する可能性があるコード範囲である。
【0079】
プリプロセッサ134は、書き換え範囲毎にソースコードを書き換える。プリプロセッサ134は、書き換え範囲の直前に、新たな一時変数を宣言する宣言文と、複数回読み出される配列要素を一時変数に代入する代入文とを挿入する。プリプロセッサ134は、書き換え範囲内の配列要素の読み出しを、一時変数の参照に置換する。これにより、プリプロセッサ134は、変換されたソースコードを出力する。
【0080】
図10は、オリジナルのソースコードの他の例を示す図である。
ここでは、ソースコード146を用いてソースコード変換方法を説明する。ソースコード146は、ソースコード記憶部131に記憶されるオリジナルのソースコードである。ソースコード146の第3行および第4行は、ソースコード141と同じである。
【0081】
ソースコード146の第6行は、配列Bのn+1番目の要素と配列Bのn-1番目の要素を読み出し、2つの要素の和を配列Bのn+0番目に書き込む処理を規定する。ソースコード146の第7行は、配列Bのn+2番目の要素と配列Bのn-1番目の要素を読み出し、2つの要素の和を配列Bのn+1番目に書き込む処理を規定する。
【0082】
ソースコード146の第9行は、配列Cのn+1番目の要素と配列Cのn-1番目の要素を読み出し、2つの要素の和を配列Cのn+0番目に書き込む処理を規定する。ソースコード146の第10行は、配列Cのn+1番目に定数を書き込み処理を規定する。ソースコード146の第11行は、配列Cのn+1番目の要素と配列Cのn-1番目の要素を読み出し、2つの要素の和を配列Cのn+1番目に書き込む処理を規定する。
【0083】
ソースコード146の第13行は、配列Dのn+1番目の要素と配列Dのn-1番目の要素を読み出し、2つの要素の和を配列Dのn+0番目に書き込む処理を規定する。ソースコード146の第14行は、変数nの値を更新する処理を規定する。ソースコード146の第15行は、配列Dのn+1番目の要素と配列Dのn-1番目の要素を読み出し、2つの要素の和を配列Dのn+1番目に書き込む処理を規定する。
【0084】
ソースコード146の第17行は、配列Eのn+1番目の要素と配列Eのn-1番目の要素を読み出し、2つの要素の和を配列Dのn+0番目に書き込む処理を規定する。ソースコード146の第18行は、配列Eのn+1番目の要素と配列Eのn-1番目の要素を読み出し、2つの要素の和を配列Dのn+1番目に書き込む処理を規定する。
【0085】
図11は、配列変数テーブルの例を示す図である。
プリプロセッサ134は、ソースコード146を解析することで配列アクセステーブル147を生成する。配列アクセステーブル147は、前述の読み出しリストと書き込みリストの役割を併せもつ。配列アクセステーブル147は、配列要素、読み出し位置、書き込み位置および書き換えフラグの項目を含む。
【0086】
配列要素は、配列名とインデックスの組で表される。読み出し位置は、ソースコード上で、配列名とインデックスの組が等号の右辺に現れる行の行番号である。書き込み位置は、ソースコード上で、配列名とインデックスの組が等号の左辺に現れる行の行番号である。書き換えフラグは、書き換え範囲が得られたか否かを示すフラグである。
【0087】
ソースコード146で読み出しが行われる配列要素は、A[n+1],A[n-1],B[n+1],B[n-1],B[n+2],C[n+1],C[n-1],D[n+1],D[n-1],E[n+1],E[n-1]である。
【0088】
A[n+1]の書き換え範囲候補は、第3行の右辺から第4行の右辺である。この書き換え範囲候補は、A[n+1]の2回の読み出しの間にA[n+0]の書き込みがあるため、書き換え範囲に該当する。A[n-1]の書き換え範囲候補は、第3行の右辺から第4行の右辺である。この書き換え範囲候補は、A[n-1]の2回の読み出しの間にA[n+0]の書き込みがあるため、書き換え範囲に該当する。
【0089】
B[n+1]の書き換え範囲候補は、第6行の右辺のみである。この書き換え範囲候補は、2回以上の読み出しを含まないため、書き換え範囲に該当しない。B[n-1]の書き換え範囲候補は、第6行の右辺から第7行の右辺である。この書き換え範囲候補は、B[n-1]の2回の読み出しの間にB[n+0]の書き込みがあるため、書き換え範囲に該当する。B[n+2]の書き換え範囲候補は、第7行の右辺のみである。この書き換え範囲候補は、2回以上の読み出しを含まないため、書き換え範囲に該当しない。
【0090】
C[n+1]の書き換え範囲候補は、第9行の右辺から第10行の左辺までの範囲と、第11行の右辺のみの範囲である。何れの範囲も2回以上の読み出しを含まないため、書き換え範囲に該当しない。C[n-1]の書き換え範囲候補は、第9行の右辺から第11行の右辺である。この書き換え範囲候補は、C[n-1]の2回の読み出しの間にC[n+0],C[n+1]の書き込みがあるため、書き換え範囲に該当する。
【0091】
D[n+1]の書き換え範囲候補は、第13行の右辺から第14行までの範囲と、第15行の右辺のみの範囲である。何れの範囲も2回以上の読み出しを含まないため、書き換え範囲に該当しない。D[n-1]の書き換え範囲候補は、第13行の右辺から第14行までの範囲と、第15行の右辺のみの範囲である。何れの範囲も2回以上の読み出しを含まないため、書き換え範囲に該当しない。
【0092】
E[n+1]の書き換え範囲候補は、第17行の右辺から第18行の右辺である。この書き換え範囲候補は、E[n+1]の2回の読み出しの間に配列Eの書き込みがないため、書き換え範囲に該当しない。E[n-1]の書き換え範囲候補は、第17行の右辺から第18行の右辺である。この書き換え範囲候補は、E[n-1]の2回の読み出しの間に配列Eの書き込みがないため、書き換え範囲に該当しない。以上から、一時変数に置換される配列要素は、A[n+1],A[n-1],B[n-1],C[n-1]である。
【0093】
図12は、変換後のソースコードの他の例を示す図である。
プリプロセッサ134は、ソースコード146をソースコード148に変換する。ソースコード148は、ソースコード記憶部132に記憶される。ソースコード148の第3行は、変数temp_1,temp_2,temp_3,temp_4を宣言している。
【0094】
ソースコード148の第4行は、配列Aのn+1番目の要素を読み出して変数temp_1に代入する処理を規定する。ソースコード148の第5行は、配列Aのn-1番目の要素を読み出して変数temp_2に代入する処理を規定する。ソースコード148の第6行は、変数temp_1,temp_2の値の和を配列Aのn+0番目に書き込む処理を規定する。ソースコード148の第7行は、変数temp_1,temp_2の値の和を配列Aのn+1番目に書き込む処理を規定する。
【0095】
ソースコード148の第9行は、配列Bのn-1番目の要素を読み出して変数temp_3に代入する処理を規定する。ソースコード148の第10行は、配列Bのn+1番目の要素を読み出して変数temp_3の値を加え、配列Bのn+0番目に書き込む処理を規定する。ソースコード148の第11行は、配列Bのn+2番目の要素を読み出して変数temp_3の値を加え、配列Bのn+1番目に書き込む処理を規定する。
【0096】
ソースコード148の第13行は、配列Cのn-1番目の要素を読み出して変数temp_4に代入する処理を規定する。ソースコード148の第14行は、配列Cのn+1番目の要素を読み出して変数temp_4の値を加え、配列Cのn+0番目に書き込む処理を規定する。ソースコード148の第16行は、配列Cのn+1番目の要素を読み出して変数temp_4の値を加え、配列Cのn+1番目に書き込む処理を規定する。
【0097】
次に、情報処理装置100の処理手順について説明する。
図13は、コンパイルの手順例を示すフローチャートである。
(S10)解析部135は、ソースコードに対して構文解析を行う。
【0098】
(S11)解析部135は、ソースコードに次のコードブロックがあるか判断する。コードブロックは、関数定義、if文、while文、for文などの制御構造に基づいて区切られた一纏まりのコード範囲である。次のコードブロックがある場合はステップS12に処理が進み、次のコードブロックがない場合はステップS28に処理が進む。
【0099】
(S12)解析部135は、コードブロックに含まれる1行のコードを読む。
(S13)解析部135は、読んだコードが配列アクセスまたはインデックス変数の更新を含むか判断する。配列アクセスまたはインデックス変数の更新を含む場合はステップS14に処理が進み、含まない場合はステップS17に処理が進む。
【0100】
(S14)解析部135は、読んだコードが配列要素の読み出しを含むか判断する。配列要素の読み出しを含む場合はステップS15に処理が進み、配列要素の書き込みまたはインデックス変数の更新を含む場合はステップS16に処理が進む。
【0101】
(S15)解析部135は、配列名とインデックスの組に、読んだコードの行番号を対応付けて、読み出しリストに記録する。そして、ステップS17に処理が進む。
(S16)解析部135は、配列名とインデックスの組に、読んだコードの行番号を対応付けて、書き込みリストに記録する。インデックス変数の更新の場合、解析部135は、そのインデックス変数を使用する配列要素を特定して記録する。
【0102】
(S17)解析部135は、コードブロックに次の行があるか判断する。次の行がある場合はステップS12に処理が戻り、次の行がない場合はステップS18に処理が進む。
図14は、コンパイルの手順例を示すフローチャート(続き1)である。
【0103】
(S18)解析部135は、ステップS15を通じて生成された読み出しリストの中から、配列名とインデックスの組を1つ選択する。
(S19)解析部135は、選択した配列名とインデックスの組について、最初の読み出し位置を検出する。読み出し位置は、読み出しリストに記録された行番号である。
【0104】
(S20)解析部135は、選択した配列名とインデックスの組について、最後の読み出し位置を検出する。ただし、最後の読み出し位置よりも前に1以上の書き込み位置がある場合、解析部135は、最初の読み出し位置の次の書き込み位置を検出する。書き込み位置は、書き込みリストに記録された行番号である。
【0105】
(S21)解析部135は、ステップS19の位置からステップS20の位置までを書き換え範囲候補と判定する。解析部135は、書き換え範囲候補内に複数回の配列要素の読み出しがあるか判断する。複数回の読み出しがある場合はステップS22に処理が進み、複数回の読み出しがない場合はステップS24に処理が進む。
【0106】
(S22)解析部135は、複数回の読み出しの間に、配列名が同じでインデックスが異なる配列要素の書き込みがあるか判断する。該当する書き込みがある場合はステップS23に処理が進み、該当する書き込みがない場合はステップS24に処理が進む。
【0107】
(S23)解析部135は、ステップS21で判定した書き換え範囲候補を、書き換え範囲として採用し、配列名とインデックスの組と対応付けて記録する。
(S24)解析部135は、読み出しリストの中に、次の配列名とインデックスの組があるか判断する。次の配列名とインデックスの組がある場合はステップS18に処理が戻り、次の配列名とインデックスの組がない場合はステップS25に処理が進む。
【0108】
(S25)書き換え部136は、採用された書き換え範囲がある配列名とインデックスの組について、一時変数を宣言する宣言文を挿入する。
(S26)書き換え部136は、書き換え範囲毎に、配列要素を読み出して一時変数に代入する代入文を、書き換え範囲の直前に挿入する。
【0109】
(S27)書き換え部136は、書き換え範囲毎に、書き換え範囲内における配列要素の読み出しを一時変数の参照に置換する。
図15は、コンパイルの手順例を示すフローチャート(続き2)である。
【0110】
(S28)書き換え部136は、変換されたソースコードを出力する。
(S29)コンパイラ137は、変換されたソースコードをコンパイルする。このとき、コンパイラ137は、ソースコードから中間コードを生成し、中間コードに対してコンパイラ最適化を行い、最適化された中間コードからオブジェクトコードを生成する。
【0111】
(S30)リンカ138は、コンパイラ137が出力したオブジェクトコードと、他のオブジェクトコードやライブラリプログラムをリンクし、実行コードを生成する。
(S31)リンカ138は、実行コードを出力する。
【0112】
以上説明したように、第2の実施の形態の情報処理装置100は、高水準言語で記述されたソースコードをコンパイルして、機械可読な実行コードを生成する。このとき、情報処理装置100は、ソースコードから生成される中間コードに対してコンパイラ最適化を行う。これにより、冗長な命令が削減されることがあり、ストールが減少するように命令の並列化や命令の実行順序の変更などの命令スケジューリングが行われることがある。よって、プログラムの実行効率が向上して実行時間が短くなる。
【0113】
また、情報処理装置100は、配列名とインデックスを用いた配列アクセスについて、RAWに該当するとコンパイラが誤って判断する可能性のあるコードを、ソースコードレベルで検出する。情報処理装置100は、書き込み後に行われる同一配列に対する読み出しが、配列名とインデックスで表現されないように、一時変数を用いてソースコードを書き換える。そして、情報処理装置100は、書き換えられたソースコードをコンパイルする。これにより、中間コードに対するコンパイラ最適化が適切に行われ、プログラムの実行効率が向上して実行時間が短くなる。
【符号の説明】
【0114】
10 情報処理装置
11 記憶部
12 処理部
13,14 ソースコード
15,16,17,18,19 コード