以下、本実施の形態を図面を参照して説明する。
[第1の実施の形態]
第1の実施の形態を説明する。
図1は、第1の実施の形態のコンパイル装置を示す図である。
第1の実施の形態のコンパイル装置10は、高級言語で記述されたソースコードを機械可読なオブジェクトコードに変換(コンパイル)する。コンパイルの中で、コンパイル装置10は、オブジェクトコードの実行効率を向上させる最適化を行う。
コンパイル装置10は、後述するように、コード13をコード14に変換する。コード13,14は、プロセッサに実行させる命令を記述したものと言うこともでき、プログラムと言うこともできる。コード13,14は、ソースコードでもよいし、ソースコードから変換された中間コードでもよい。また、コード13,14は、アセンブリ言語で記述されたアセンブリコードでもよいし、オブジェクトコードでもよい。また、コンパイル装置10は、ユーザが操作する端末装置でもよいし、端末装置からアクセスされるサーバ装置でもよい。コンパイル装置10を、コンピュータを用いて実装してもよい。
コンパイル装置10は、記憶部11および変換部12を有する。記憶部11は、コード13を記憶する。記憶部11は、RAM(Random Access Memory)などの揮発性の記憶装置でもよいし、HDD(Hard Disk Drive)やフラッシュメモリなどの不揮発性の記憶装置でもよい。変換部12は、記憶部11に記憶されたコード13をコード14に変換する。変換部12は、コード14を記憶部11に保存してもよい。変換部12は、CPU(Central Processing Unit)やDSP(Digital Signal Processor)などのプロセッサでもよいし、ASIC(Application Specific Integrated Circuit)やFPGA(Field Programmable Gate Array)などの特定用途の電子回路を含んでもよい。プロセッサは、例えば、記憶部11または他の記憶装置に記憶されたコンパイルプログラムを実行する。なお、複数のプロセッサの集合(マルチプロセッサ)を「プロセッサ」と呼んでもよい。
コード13には、変数15の値と比較値16a,16b,16cを含む3以上の比較値それぞれとを比較する比較処理が記述されている。また、コード13には、比較結果に応じた分岐制御が記述されている。例えば、変数15が整数型であり、比較値16aが「10」、比較値16bが「20」、比較値16cが「30」である。ただし、文字は文字コードとしての整数で表現され得るため、変数15が文字型であってもよい。
例えば、コード13は、変数15の値と比較値16aとを比較する1番目の比較命令と、1番目の比較結果が真になる(値が一致する)場合に処理Yにジャンプする1番目の分岐命令を含む。また、例えば、コード13は、変数15の値と比較値16bとを比較する2番目の比較命令と、2番目の比較結果が真になる(値が一致する)場合に処理Yにジャンプする2番目の分岐命令を含む。また、例えば、コード13は、変数15の値と比較値16cとを比較する3番目の比較命令と、3番目の比較結果が真になる(値が一致する)場合に処理Yにジャンプする3番目の分岐命令を含む。
上記の3つの比較命令は、比較する一方の値(変数15の値)が同じであり、他方の値(比較値16a,16b,16c)が異なる。また、上記の3つの分岐命令は、比較結果が真の場合のジャンプ先(処理Y)が同じである。3つの比較結果が全て偽である場合、処理Xが実行される。これは、変数15の値が「10」,「20」,「30」の何れかである場合は処理Yが実行され、それ以外の場合は処理Xが実行されることを示す。
変換部12は、コード13の中から、変数15の値と3以上の比較値それぞれとを比較して分岐制御を行う命令群を検出する。変換部12は、3以上の比較値の中から、最小の比較値と最大の比較値を判定する。最小の比較値は、変数15が取り得る値の範囲(変数15の値域)の下限よりも大きい可能性がある。また、最大の比較値は、変数15の値域の上限よりも小さい可能性がある。例えば、比較値16a,16b,16cのうち、比較値16aが最小の比較値であり、比較値16cが最大の比較値である。変換部12は、判定した最小の比較値と最大の比較値に基づいて、コード13をコード14に変換する。
コード14には、変数15の値と最小の比較値および最大の比較値とを比較する比較処理が記述されている。また、コード14には、変数15の値が最小の比較値より小さいかまたは最大の比較値より大きい場合、少なくとも最小の比較値および最大の比較値以外の比較値との比較を迂回する分岐制御が記述されている。変数15の値が最小の比較値より小さいかまたは最大の比較値より大きいことの判定は、例えば、コード13に記述された変数15の値と各比較値との間の個別の比較処理よりも前に挿入される。
例えば、コード14は、変数15の値と最小の比較値16aとを比較する1番目の追加の比較命令と、変数15の値が比較値16aより小さい場合に処理Xにジャンプする1番目の追加の分岐命令を含む。また、例えば、コード14は、変数15の値と最大の比較値16cとを比較する2番目の追加の比較命令と、変数15の値が比較値16cより大きい場合に処理Xにジャンプする2番目の追加の分岐命令を含む。また、例えば、コード14は、これらの追加の比較命令および追加の分岐命令の後に、コード13と同様の比較値16a,16b,16cに関する3つの比較命令および3つの分岐命令を含む。
変数15の値が最小の比較値より小さい場合、変数15の値は3以上の比較値の何れとも一致しないことが明らかである。よって、この場合には、変数15の値と3以上の比較値それぞれとの個別の比較を実行せず、処理Xにジャンプすることが可能である。また、変数15の値が最大の比較値より大きい場合、変数15の値は3以上の比較値の何れとも一致しないことが明らかである。よって、この場合にも、変数15の値と3以上の比較値それぞれとの個別の比較を実行せず、処理Xにジャンプすることが可能である。
コード14には、3以上の比較値についての個別の比較の前に、それら個別の比較を迂回して(実行せずに)処理Xにジャンプするパス(実行経路)が挿入されていると言うこともできる。一方、変数15の値が最小の比較値以上かつ最大の比較値以下である場合、変数15の値は3以上の比較値の何れかと一致する可能性がある。よって、この場合には、例えば、3以上の比較値についての個別の比較の少なくとも一部が実行され得る。
第1の実施の形態のコンパイル装置10によれば、コード13から、同じ変数15の値と比較される3以上の比較値の中から最小の比較値と最大の比較値が判定される。そして、変数15の値が最小の比較値より小さいかまたは最大の比較値より大きい場合には他の比較値との比較が迂回されるように、コード13がコード14に変換される。
これにより、変数15の値が最小の比較値より小さいかまたは最大の比較値より大きい場合にはそれ以降の比較命令が実行されず、変数15の値1つ当たりの実行時の平均の比較回数が削減される。よって、3以上の比較値についての比較処理の負荷を軽減することができる。これは、比較値の個数と比べて変数15の値域が広く、変数15の値が何れの比較値とも一致しない可能性が高い場合に特に有効である。また、比較値が多く、変数15の値と全ての比較値とを比較すると比較処理の負荷が大きい場合に特に有効である。
例えば、比較値を比較結果が真になる確率が高い順にソートするだけでは、変数15の値が何れの比較値とも一致しない場合、変数15の値と全ての比較値とを比較することになってしまう。また、比較値の間で真になる確率の差が小さい(ばらつきが小さい)場合には、比較回数を削減することが難しい。これに対し、コード14では、変数15の値が何れの比較値とも一致しない場合でも比較回数を削減することができる。また、コンパイル装置10は、比較結果が真になる確率を収集しなくてもよく、オブジェクトコードをテスト実行するコストやコンパイルのコストを削減することができる。
また、変数15の値1つ当たりの比較回数が削減されることで、分岐命令の実行回数が削減されることがある。分岐命令の実行回数を削減することで、オブジェクトコードを実行するプロセッサのパイプライン処理において、分岐予測の失敗により生じる再実行コスト(ペナルティ)を削減できる。よって、オブジェクトコードの実行効率を向上させることができる。これは、分岐予測の精度が高くないプロセッサでは特に有効である。
[第2の実施の形態]
次に、第2の実施の形態を説明する。
図2は、コンパイル装置のハードウェア例を示すブロック図である。
コンパイル装置100は、CPU101、RAM102、HDD103、画像信号処理部104、入力信号処理部105、媒体リーダ106および通信インタフェース107を有する。CPU101、RAM102、HDD103、画像信号処理部104、入力信号処理部105、媒体リーダ106および通信インタフェース107は、バス108に接続されている。なお、コンパイル装置100は、第1の実施の形態のコンパイル装置10に対応する。CPU101は、第1の実施の形態の変換部12に対応する。RAM102またはHDD103は、第1の実施の形態の記憶部11に対応する。
CPU101は、プログラムの命令を実行する演算回路を含むプロセッサである。CPU101は、HDD103に記憶されたプログラムやデータの少なくとも一部をRAM102にロードし、プログラムを実行する。なお、CPU101は複数のプロセッサコアを備えてもよく、コンパイル装置100は複数のプロセッサを備えてもよく、以下で説明する処理を複数のプロセッサまたはプロセッサコアを用いて並列に実行してもよい。また、複数のプロセッサの集合(マルチプロセッサ)を「プロセッサ」と呼んでもよい。
RAM102は、CPU101が実行するプログラムやCPU101が演算に用いるデータを一時的に記憶する揮発性の半導体メモリである。なお、コンパイル装置100は、RAM以外の種類のメモリを備えてもよく、複数個のメモリを備えてもよい。
HDD103は、OS(Operating System)やミドルウェアやアプリケーションソフトウェアなどのソフトウェアのプログラム、および、データを記憶する不揮発性の記憶装置である。プログラムには、コンパイルプログラムが含まれる。なお、コンパイル装置100は、フラッシュメモリやSSD(Solid State Drive)などの他の種類の記憶装置を備えてもよく、複数の不揮発性の記憶装置を備えてもよい。
画像信号処理部104は、CPU101からの命令に従って、コンパイル装置100に接続されたディスプレイ111に画像を出力する。ディスプレイ111としては、CRT(Cathode Ray Tube)ディスプレイ、液晶ディスプレイ(LCD:Liquid Crystal Display)、プラズマディスプレイ、有機EL(OEL:Organic Electro-Luminescence)ディスプレイなどを用いることができる。
入力信号処理部105は、コンパイル装置100に接続された入力デバイス112から入力信号を取得し、CPU101に出力する。入力デバイス112としては、マウスやタッチパネルやタッチパッドやトラックボールなどのポインティングデバイス、キーボード、リモートコントローラ、ボタンスイッチなどを用いることができる。また、コンパイル装置100に、複数の種類の入力デバイスが接続されていてもよい。
媒体リーダ106は、記録媒体113に記録されたプログラムやデータを読み取る読み取り装置である。記録媒体113として、例えば、フレキシブルディスク(FD:Flexible Disk)やHDDなどの磁気ディスク、CD(Compact Disc)やDVD(Digital Versatile Disc)などの光ディスク、光磁気ディスク(MO:Magneto-Optical disk)、半導体メモリなどを使用できる。媒体リーダ106は、例えば、記録媒体113から読み取ったプログラムやデータをRAM102またはHDD103に格納する。
通信インタフェース107は、ネットワーク114に接続され、ネットワーク114を介して他の装置と通信を行うインタフェースである。通信インタフェース107は、スイッチなどの通信装置とケーブルで接続される有線通信インタフェースでもよいし、基地局と無線リンクで接続される無線通信インタフェースでもよい。
なお、コンパイル装置100は、ユーザが操作する端末装置でもよいし、端末装置または他のサーバ装置からネットワーク114を介してアクセスされるサーバ装置でもよい。コンパイル装置100は、媒体リーダ106を備えていなくてもよく、ユーザが操作する端末装置から制御可能である場合には画像信号処理部104や入力信号処理部105を備えていなくてもよい。また、ディスプレイ111や入力デバイス112が、コンパイル装置100の筐体と一体に形成されていてもよい。
図3は、コンパイル装置の機能例を示すブロック図である。
コンパイル装置100は、ソースコード記憶部121、中間コード記憶部122、オブジェクトコード記憶部123、実行ファイル記憶部124、制御情報記憶部125、コンパイラ131およびリンカ137を有する。ソースコード記憶部121、中間コード記憶部122、オブジェクトコード記憶部123、実行ファイル記憶部124および制御情報記憶部125は、RAM102またはHDD103に確保した記憶領域を用いて実現できる。コンパイラ131およびリンカ137は、CPU101が実行するプログラム(コンパイルプログラムおよびリンクプログラム)を用いて実現できる。ただし、コンパイラ131およびリンカ137を、特定用途の電子回路を用いて実現してもよい。
ソースコード記憶部121は、ソースコードを記憶する。ソースコードは、C言語などの高級言語で記述されたプログラムである。ユーザは、入力デバイス112などを用いてコンパイル装置100に対してソースコードを直接入力してもよいし、ネットワーク114を介してコンパイル装置100にソースコードを送信してもよい。中間コード記憶部122は、中間コードを記憶する。中間コードは、コンパイル装置100の内部で利用される中間言語で記述されたプログラムであり、ソースコードに対応する。
オブジェクトコード記憶部123は、オブジェクトコードを記憶する。オブジェクトコードは、プロセッサが解釈可能な機械語で記述されたプログラムであり、ソースコードや中間コードに対応する。実行ファイル記憶部124は、実行ファイルを記憶する。実行ファイルは、CPUが実行できるプログラムであり、オブジェクトコードとライブラリなどへのリンクとを含む。実行ファイルは、CPU101が実行してもよいし、コンパイル装置100が備える他のCPUまたはコンパイル装置100以外のコンピュータのCPUが実行してもよい。コンパイラ131は、ターゲットのCPUアーキテクチャに応じて、オブジェクトコードに使用する命令を変更する。制御情報記憶部125は、コンパイラ131が最適化に使用する各種の制御情報を記憶する。制御情報の詳細は後述する。
コンパイラ131は、ソースコードをオブジェクトコードに変換する。コンパイラ131は、ソースコード入力部132、中間コード生成部133、最適化部134、アセンブリコード生成部135およびオブジェクトコード出力部136を有する。
ソースコード入力部132は、ユーザからコンパイルコマンドを受け付け、コンパイルコマンドで指定されたソースコードをソースコード記憶部121から読み出す。中間コード生成部133は、ソースコード入力部132が読み出したソースコードを解析し、ソースコードを中間コードに変換する。ソースコードの解析には、字句解析、構文解析、意味解析などのいわゆるフロントエンド処理が含まれる。中間コード生成部133は、生成した中間コードを中間コード記憶部122に格納する。
最適化部134は、中間コード記憶部122に記憶された中間コードに対して、実行速度が向上するように各種の最適化を行う。最適化部134は、中間コードを解析し、所定の規則に従って中間コードを書き換える。最適化には、ターゲットのCPUアーキテクチャ(オブジェクトコードを実行させる予定のCPUの種類)に応じた命令変換も含まれる。ターゲットのCPUアーキテクチャは、予め決まっていてもよいし、コンパイルコマンドのオプションとしてユーザから指定されてもよい。最適化の詳細は後述する。
アセンブリコード生成部135は、中間コード記憶部122から最適化後の中間コードを読み出し、低級言語であるアセンブリ言語で記述されたアセンブリコードに変換する。オブジェクトコード出力部136は、アセンブリコード生成部135が生成したアセンブリコードをオブジェクトコードに変換する。アセンブリコードの命令とオブジェクトコードの命令とは、通常は1対1に対応する。オブジェクトコード出力部136は、生成したオブジェクトコードをオブジェクトコード記憶部123に格納する。
リンカ137は、オブジェクトコード記憶部123からオブジェクトコードを読み出し、オブジェクトコードから参照されている他のオブジェクトコードやライブラリを検出する。リンカ137は、読み出したオブジェクトコードと検出した他のオブジェクトコードやライブラリとをリンクし、実行ファイルを生成する。リンカ137は、生成した実行ファイルを実行ファイル記憶部124に格納する。なお、コンパイラ131のコンパイル機能とリンカ137のリンク機能とが、1つのモジュールに統合されてもよい。
図4は、最適化部の機能例を示すブロック図である。
最適化部134は、汎用最適化部141、ループ最適化部142、SIMD(Single Instruction Multiple Data)最適化部143、命令変換部144、マシン依存最適化部145および命令スケジューリング部148を有する。
汎用最適化部141は、中間コードに対して汎用的な最適化を実行する。汎用的な最適化には、例えば、使用されていない変数の削除、静的に決定できる値のみに依存する計算式の定数化、複数の計算式に共通に含まれる部分式の計算結果の再利用などが含まれる。
ループ最適化部142は、中間コードの中からループを検出し、ループに対して最適化を実行する。ループの最適化には、例えば、ループ内で値が変わらない変数に関する演算をループ外に移動することが含まれる。また、ループの最適化には、例えば、ループ内の命令を展開(アンローリング)して、i回目(iは正の整数)の処理を示す命令とi+1回目の処理を示す命令に分解し、ループの繰り返し数を減らすことなどが含まれる。
SIMD最適化部143は、ターゲットのCPUアーキテクチャがSIMD命令をサポートしている場合、中間コードの中からSIMD命令に変換可能な2以上の命令の組を検出する。SIMD命令に変換可能な命令の組は、依存関係がなく演算の種類が同じスカラ命令(非SIMD命令)の組である。SIMD命令は、異なるデータに対する同じ種類の演算を並列に実行する命令である。SIMD最適化部143は、検出した2以上の命令の組をSIMD命令にマージして、中間コードの命令数を削減する。
命令変換部144は、中間コードで使用されている命令形式を、ターゲットのCPUアーキテクチャがサポートする命令セットの命令形式に変換する。すなわち、命令変換部144は、CPU非依存の中間コードをCPU依存の中間コードに変換する。命令変換部144は、1つのCPUアーキテクチャのみに対応していてもよいし、複数のCPUアーキテクチャに対応していてもよい。後者の場合、例えば、ターゲットのCPUアーキテクチャがユーザから指定される。コンパイラ131は、各CPUアーキテクチャがサポートする命令セットを示すプロセッサ情報を保持していてもよい。
マシン依存最適化部145は、CPU依存の命令の種類(ターゲットのCPUアーキテクチャに特有の命令の種類など)を活用した最適化を行う。CPU依存の命令の種類には、後述するような各種の分岐命令が含まれる。第2の実施の形態では特に、1つの変数の値と複数の比較値とを比較し比較結果に応じて処理が分岐する制御構造を最適化することを考える。マシン依存最適化部145は、解析部146および変換部147を有する。
解析部146は、中間コードの中から、複数の比較値それぞれについて、ある変数の値と当該比較値とを比較する比較命令と、両者が一致する場合に所定の命令にジャンプする分岐命令とを検出する。解析部146は、変数の値域と比較値の個数とに基づいて、比較パターン数が最小となる制御構造を判定する。変換部147は、解析部146の解析結果に基づいて、変数の値1つ当たりの平均の比較回数が減少するように中間コードを書き換える。このとき、変換部147は、既存の比較命令および分岐命令を並べ替える。また、変換部147は、新たな比較命令および分岐命令を挿入することで、既存の比較命令および分岐命令の少なくとも一部を迂回する実行経路を作成する。
命令スケジューリング部148は、中間コードに含まれる命令の順序を変更するスケジューリングを行う。スケジューリングには、例えば、依存関係のない2以上の命令を検出し、検出した2以上の命令を異なるCPUまたは異なるCPUコアに割り当てる並列化が含まれる。また、スケジューリングには、例えば、パイプラインが効率的に動作するように、依存関係のない2以上の命令の間で実行順序を入れ替えることが含まれる。
次に、ターゲットのCPUについて説明する。
図5は、プロセッサのレジスタ構成例を示すブロック図である。
CPU20は、コンパイル装置100によって生成された実行ファイルを実行可能なプロセッサの1つである。CPU20は、コンパイル装置100が備えてもよいし、他のコンピュータが備えてもよい。CPU20は、汎用レジスタ21a,21b,21c(r1,r2,r3)を含む複数の汎用レジスタと、ステータスレジスタ22を有する。
汎用レジスタ21a,21b,21cは、演算に使用するデータを一時的に記憶する揮発性の記憶素子(レジスタ)である。汎用レジスタ21a,21b,21cは、実行ファイルに含まれるユーザ命令から明示的に指定することができる。ステータスレジスタ22は、演算の実行状況を示す制御フラグなどを記憶するレジスタである。ステータスレジスタ22は、実行ファイルに含まれるユーザ命令からは明示的に指定されず、演算の進行に応じてCPU20によって自動的に更新される。制御フラグには、ゼロフラグ(Z)、ネガティブフラグ(N)およびオーバフローフラグ(V)が含まれる。
ゼロフラグは、演算結果が0か否かを示す。ゼロフラグは、例えば、1ビットで表現できる。数値演算が実行される毎にゼロフラグが更新される。演算結果が0の場合はゼロフラグがON(1)に更新され、演算結果が0以外の場合はゼロフラグがOFF(0)に更新される。2つの数値を比較する比較演算は、CPU20の内部では除算として実装される。このため、比較演算において2つの数値が一致する場合はゼロフラグがONに更新され、2つの数値が一致しない場合はゼロフラグがOFFに更新される。
ネガティブフラグは、演算結果が負の値か否かを示す。ネガティブフラグは、例えば、1ビットで表現できる。数値演算が実行される毎にネガティブフラグが更新される。演算結果が負の値の場合はネガティブフラグがON(1)に更新され、演算結果が0以上(非負の値)の場合はネガティブフラグがOFF(0)に更新される。
オーバフローフラグは、演算結果がオーバフローしたか否かを示す。オーバフローは、変数の桁数(ビット数)が不足し、演算結果が変数の型の上限値を超えたかまたは下限値を下回ったことである。例えば、ある変数の型が4ビットの符号付き整数である場合、当該変数の値域は−8〜7である。この場合、演算結果が−8より小さいかまたは7より大きくなると、オーバフローが発生する。オーバフローが発生すると、変数が演算結果を正しく表現しないことになる。オーバフローフラグは、例えば、1ビットで表現できる。数値演算が実行される毎にオーバフローフラグが更新される。オーバフローが発生した場合はオーバフローフラグがON(1)に更新され、オーバフローが発生していない場合はオーバフローフラグがOFF(0)に更新される。
図6は、プロセッサ情報の例を示す図である。
プロセッサ情報151は、あるCPUアーキテクチャがサポートする命令の種類を示す。コンパイラ131は、ターゲットのCPUアーキテクチャに対応するオブジェクトコードを生成するために、プロセッサ情報151を保持していてもよい。プロセッサ情報151には、命令の種類として、cmp命令、beq命令、bne命令、bl命令、bg命令、bge命令およびba命令が記載されている。第2の実施の形態では、ターゲットのCPUアーキテクチャがこれらの命令をサポートしているものとする。すなわち、上記のCPU20がこれらの命令を実行することができる。
cmp命令は、数値を示す2つのオペランド(オペランドA,B)の値を比較する比較命令である。前述のように、cmp命令は除算A−Bとして実装される。オペランドA,Bの値が一致する場合、ゼロフラグがON(Z=1)に更新される。オペランドAの値がオペランドBの値よりも小さい場合、ネガティブフラグがON(N=1)に更新される。除算A−Bの結果が変数の型の上限値より大きいかまたは下限値より小さい場合、オーバフローフラグがON(V=1)に更新される。
beq命令は、ゼロフラグがONの場合にオペランドlabelが示す命令にジャンプし、ゼロフラグがOFFの場合にはジャンプしない条件分岐命令である。beq命令の直前にcmp命令が実行された場合、beq命令は、オペランドA,Bの値が一致する場合にジャンプし一致しない場合はジャンプしないことを示す。
bne命令は、ゼロフラグがOFFの場合にオペランドlabelが示す命令にジャンプし、ゼロフラグがONの場合にはジャンプしない条件分岐命令である。bne命令の直前にcmp命令が実行された場合、bne命令は、オペランドA,Bの値が一致しない場合にジャンプし一致する場合はジャンプしないことを示す。
bl命令は、ネガティブフラグとオーバフローフラグの排他的論理和(N xor V)が1の場合にオペランドlabelが示す命令にジャンプし、排他的論理和が0の場合にはジャンプしない条件分岐命令である。bl命令の直前にcmp命令が実行された場合、bl命令は、オペランドAの値がオペランドBの値より小さい場合(A<B)にジャンプしそれ以外の場合(A≧B)にジャンプしないことを示す。
bg命令は、ゼロフラグとネガティブフラグとオーバフローフラグから算出される値が1の場合にオペランドlabelが示す命令にジャンプし、0の場合にはジャンプしない条件分岐命令である。上記の値は、ネガティブフラグとオーバフローフラグの排他的論理和を算出し、排他的論理話とゼロフラグとの論理和を算出し、論理和を否定することで算出される(not(Z or(N xor V)))。bg命令の直前にcmp命令が実行された場合、bg命令は、オペランドAの値がオペランドBの値より大きい場合(A>B)にジャンプしそれ以外の場合(A≦B)にジャンプしないことを示す。
bge命令は、ネガティブフラグとオーバフローフラグの排他的論理和の否定(not(N xor V))が1の場合にオペランドlabelが示す命令にジャンプし、排他的論理和の否定が0の場合にはジャンプしない条件分岐命令である。bge命令の直前にcmp命令が実行された場合、bge命令は、オペランドAの値がオペランドBの値以上の場合(A≧B)にジャンプしそれ以外の場合(A<B)にジャンプしないことを示す。
ba命令は、オペランドlabelが示す命令に常にジャンプする無条件分岐命令である。ba命令の直前にcmp命令が実行されても、ba命令は比較結果に依存しない。
次に、マシン依存最適化部145によって行われる最適化について説明する。
図7は、連続する分岐命令を含むプログラムの例を示す図である。
中間コード生成部133は、コード161をコード162に変換し、コード162をコード163に変換する。図7では、コード161,162をソースコード形式で記述しており、コード163を疑似アセンブラ形式で記述している。実際には、コード163は、コンパイル装置100の内部で使用される中間言語を用いて記述される。マシン依存最適化部145は、中間コードに対して最適化を実行することになる。
コード161には、文字型の変数cと論理型の変数bを引数として受け取る関数fooが定義されている。変数cは1文字を示す。ただし、文字は所定バイト数の文字コードで表現されることから、内部では変数cの値は整数である。変数bはtrueまたはfalseを示す。ただし、内部ではfalseは0で表現され、trueは0以外の整数で表現される。関数fooは、変数cの示す文字が所定の複数の文字の何れとも一致せず、かつ、変数bの値がfalseであるか判定する。所定の複数の文字は、改行、スペース、タブ、復帰、ダブルクォテーション(”)、バックスラッシュ(\)、スラッシュ(/)、セミコロン(;)、左括弧({)および右括弧(})である。関数fooは、上記条件を満たす場合は処理Xを実行し、上記条件を満たさない場合は処理Yを実行する。
コード162には、コード161と同様の関数fooが定義されている。ただし、コード162では、変数cの値と比較される文字が文字コードを示す整数に置換されている。「10」は改行を示し、「32」はスペースを示し、「9」はタブを示し、「13」は復帰を示す。「34」はダブルクォテーションを示し、「39」はバックスラッシュを示し、「47」はスラッシュを示し、「59」はセミコロンを示し、「123」は左括弧を示し、「125」は右括弧を示す。これら文字コードに相当する10個の整数が、変数cの値と比較される比較値になる。また、コード162では、変数bの値と比較される論理値が整数に置換されている。「0」はfalseを示す。
コード163は、コード162の処理を、CPU20がサポートするcmp命令、beq命令、bne命令およびload命令を用いて表現したものである。load命令は、メモリから汎用レジスタにデータをロードする命令である。コード163は、11個のcmp命令、10個のbeq命令、1個のbne命令および1個のload命令を含む。
コード163では、ラベルL1において、変数cの値と「10」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。次に、ラベルL2において、変数cの値と「32」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。次に、ラベルL3において、変数cの値と「9」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。
次に、ラベルL4において、変数cの値と「13」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。次に、ラベルL5において、メモリから変数bの値をロードするload命令が実行され、変数bの値と「0」とを比較するcmp命令が実行され、両者が一致しない場合にラベルL13にジャンプするbne命令が実行される。
次に、ラベルL6において、変数cの値と「34」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。次に、ラベルL7において、変数cの値と「39」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。次に、ラベルL8において、変数cの値と「47」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。
次に、ラベルL9において、変数cの値と「59」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。次に、ラベルL10において、変数cの値と「123」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。次に、ラベルL7において、変数cの値と「125」とを比較するcmp命令が実行され、両者が一致する場合にラベルL13にジャンプするbeq命令が実行される。
上記の何れの分岐命令(beq命令およびbne命令)によってもジャンプしなかった場合、ラベルL12において処理Xが実行される。上記の何れかの分岐命令によってジャンプした場合、ラベルL13において処理Yが実行される。すなわち、コード163では、変数cの値が「10」,「32」,「9」,「13」,「34」,「39」,「47」,「59」,「123」,「125」の何れかと一致するか、または、変数bの値が「0」でない場合、処理Yが実行される。それ以外の場合は処理Xが実行される。このコード163の処理は、コード162が示す処理と等価である。
図8は、ブロック情報の例を示す図である。
マシン依存最適化部145が最適化を行うにあたり、上記のコード163から、図8に示すようなブロック情報が生成されて制御情報記憶部125に格納される。ブロック情報は、中間コードのブロック毎に生成される。1つのブロックは、連続的に実行されるひとまとまりの命令の集合を示す。分岐命令は、ブロックを区切る1つの基準となる。第2の実施の形態では、上記のコード163の各ラベルが1つのブロックに対応する。
ブロック情報152aはラベルL1に対応し、ブロック情報152bはラベルL2に対応し、ブロック情報152cはラベルL3に対応する。ブロック情報152dはラベルL4に対応し、ブロック情報152eはラベルL5に対応し、ブロック情報152fはラベルL6に対応し、ブロック情報152gはラベルL7に対応する。ブロック情報152hはラベルL8に対応し、ブロック情報152iはラベルL9に対応し、ブロック情報152jはラベルL10に対応し、ブロック情報152kはラベルL11に対応する。
各ブロック情報は、ブロック名(項目#A)、比較値(項目#B)、境界フラグ(項目#C)、隙間フラグ(項目#D)、分岐点フラグ(項目#E)、連続フラグ(項目#F)、真ブロック(項目#G)および偽ブロック(#H)を含む。また、各ブロック情報は、blフラグ(項目#I)、bgフラグ(項目#J)、bgeフラグ(項目#K)、baフラグ(項目#L)、前ポインタ(項目#M)および次ポインタ(項目#N)を含む。
ブロック名は、ブロックを識別する識別情報である。例えば、ブロック名にはラベルが用いられる。比較値は、変数の値と比較される固定値であり、ブロックに含まれるcmp命令の第2オペランドの値である。ただし、後述する連続フラグがfalseのブロックについては、比較値を−1に設定する。境界フラグは、後述する境界判定のブロックであるか否かを示す。隙間フラグは、後述する隙間判定のブロックであるか否かを示す。分岐点フラグは、後述する分岐点判定のブロックであるか否かを示す。境界判定、隙間判定および分岐点判定のブロックは、最適化を通じて中間コードに挿入される。境界フラグ、隙間グラフおよび分岐点フラグの初期値はfalseである。
連続フラグは、ブロックに含まれるcmp命令が他のブロックと同じ変数を第1オペランドに指定しているか、すなわち、同じ変数に対する連続する比較処理であるかを示す。前述のコード163の場合、ラベルL1〜L4,L6〜L11のブロックは同じ変数cを比較対象とするため、連続フラグがtrueになる。一方、ラベルL5のブロックは変数bを比較対象とするため、連続フラグがfalseになる。真ブロックは、分岐命令のジャンプ先の命令が属するブロックである。偽ブロックは、分岐命令でジャンプしない場合に次に実行される命令、すなわち、分岐命令の次の命令が属するブロックである。
blフラグは、ブロック末尾の分岐命令としてbl命令が用いられるか否かを示す。bl命令は、後述する境界判定のブロックや隙間判定のブロックで使用されることがある。bgフラグは、ブロック末尾の分岐命令としてbg命令が用いられるか否かを示す。bg命令は、後述する境界判定のブロックで使用されることがある。bgeフラグは、ブロック末尾の分岐命令としてbge命令が用いられるか否かを示す。bge命令は、後述する分岐点判定のブロックで使用されることがある。blフラグ、bgフラグおよびbgeフラグの初期値はfalseである。baフラグは、ブロック末尾にba命令が挿入されるか否かを示す。baフラグの初期値はfalseである。
前ポインタは、そのブロックの1つ前に配置されるブロックを示す。先頭のブロックの前ポインタはNULLである。次ポインタは、そのブロックの1つ後ろに配置されるブロックを示す。制御情報記憶部125には、ブロック情報の列の末尾を示すダミーのブロック情報が格納される。末尾のブロック情報の次ポインタはNULLである。
例えば、ブロック情報152aの生成当初の内容は、ブロック名がL1、比較値が10、境界フラグがfalse、隙間フラグがfalse、分岐点フラグがfalse、連続フラグがtrue、真ブロックがL13、偽ブロックがL2である。また、blフラグがfalse、bgフラグがfalse、bgeフラグがfalse、baフラグがfalse、前ポインタがNULL、次ポインタがL2である。各ブロック情報の内容は、最適化方法を検討する過程で順次更新される。なお、以下では、境界フラグ、隙間フラグ、分岐点フラグ、blフラグ、bgフラグ、bgeフラグおよびbaフラグについては、値がfalse(初期値)である場合はその記載を省略することがある。
図9は、比較値ベクトルと間隔マップと命令テーブルの例を示す図である。
マシン依存最適化部145が最適化を行う過程で、比較値ベクトル153、間隔マップ154および命令テーブル155が生成されて制御情報記憶部125に格納される。
比較値ベクトル153は、インデックスと比較値とを対応付ける。インデックスは、0から始まる連続する非負整数である。比較値は、同じ変数の値(例えば、コード163の変数cの値)と比較される整数の固定値である。他とは異なる変数の値(例えば、コード163の変数bの値)と比較される整数の固定値は、比較値から除外される。比較値ベクトル153では、複数の比較値が昇順にソートされる。比較値ベクトル153のサイズは、比較値の個数を示す。例えば、前述のコード163から、比較値「9」,「10」,「13」,「32」,「34」,「39」,「47」,「59」,「123」,「125」を含むサイズ10の比較値ベクトル153が生成される。
間隔マップ154は、間隔と比較値とを対応付ける。間隔は、ある比較値とその次に大きい比較値との間に存在する比較されない整数の個数である。間隔は、隣接する2つの比較値のうちの小さい方の比較値と対応付けられる。ただし、間隔マップ154には、間隔「0」は登録されない。間隔マップ154では、複数の間隔が降順にソートされる。
例えば、比較値「59」と比較値「123」の間には63個の整数が存在するため、間隔「63」と比較値「59」が登録される。また、比較値「13」と比較値「32」の間には18個の整数が存在するため、間隔「18」と比較値「13」が登録される。同様にして、間隔「11」と比較値「47」、間隔「7」と比較値「39」、間隔「4」と比較値「34」、間隔「2」と比較値「10」、間隔「1」と比較値「32」、間隔「1」と比較値「123」が、間隔マップ154に登録される。
命令テーブル155は、比較値と命令種類とを対応付ける。命令種類は、ある比較値が属するブロックで使用される分岐命令の種類を示す。図9の例では、比較値「39」とbge命令、比較値「34」とba命令、比較値「13」とbge命令、比較値「10」とba命令、比較値「59」とbge命令、比較値「47」とba命令が対応付けられている。命令テーブル155の内容は、前述のブロック情報のbgeフラグやbaフラグに反映される。比較値と命令種類との対応付け方法については後述する。
図10は、数値判定の最適化例を示す図である。
マシン依存最適化部145は、前述のコード163が示す制御構造を、変数cの値1つ当たりの平均の比較回数が減少するように、図10に示すような制御構造に変換する。変数cの値に対する一連の判定処理は、境界判定164a、隙間判定164b、分岐点判定164c,164d,164eおよび個別判定164f,164g,164h,164i,164j,164k,164l,164m,164n,164oを含む。
個別判定164f,164g,164h,164i,164j,164k,164l,164m,164n,164oは、前述のコード163におけるラベルL1〜L4,L6〜L11に対応する。すなわち、個別判定164fは、変数cの値が「9」であるか判定する。個別判定164gは、変数cの値が「10」であるか判定する。個別判定164hは、変数cの値が「13」であるか判定する。個別判定164iは、変数cの値が「32」であるか判定する。個別判定164jは、変数cの値が「34」であるか判定する。個別判定164kは、変数cの値が「39」であるか判定する。個別判定164lは、変数cの値が「47」であるか判定する。個別判定164mは、変数cの値が「59」であるか判定する。個別判定164nは、変数cの値が「123」であるか判定する。個別判定164oは、変数cの値が「125」であるか判定する。
この一連の判定処理では、個別判定164f,164g,164h,164i,164j,164k,164l,164m,164n,164oの前に、境界判定164a、隙間判定164bおよび分岐点判定164c,164d,164eが挿入される。
境界判定164aは、変数cの値が最小の比較値「9」より小さいかまたは最大の比較値「125」より大きいか判定する。境界判定164aの判定結果が真である場合、変数cの値が何れの比較値とも一致しないことが明らかである。この場合、隙間判定164b、分岐点判定164c,164d,164eおよび個別判定164f,164g,164h,164i,164j,164k,164l,164m,164n,164oをスキップして、処理Xにジャンプすることが可能である。
境界判定164aの判定結果が偽である場合、隙間判定164bが実行される。隙間判定164bは、変数cの値が比較値「60」以上でかつ比較値「123」より小さいか判定する。隙間判定164bの判定結果が真である場合、「59」と「123」の間に他の比較値が存在しないため、変数cの値が何れの比較値とも一致しないことが明らかである。この場合、分岐点判定164c,164d,164eおよび個別判定164f,164g,164h,164i,164j,164k,164l,164m,164n,164oをスキップして、処理Xにジャンプすることが可能である。なお、図10では最も広い間隔のみについて隙間判定を行っているが、2以上の間隔について隙間判定を行ってもよい。隙間判定を行うか否かの基準については後述する。
隙間判定164bの判定結果が偽である場合、分岐点判定164cが実行される。分岐点判定164cは、変数cの値が比較値「39」以上であるか判定する。分岐点判定164cの判定結果が真である場合、次に分岐点判定164dが実行される。分岐点判定164cの判定結果が偽である場合、次に分岐点判定164eが実行される。
分岐点判定164dは、変数cの値が比較値「13」以上であるか判定する。分岐点判定164dの判定結果が真である場合、個別判定164fにジャンプする。分岐点判定164dの判定結果が偽である場合、個別判定164hにジャンプする。分岐点判定164eは、変数cの値が比較値「59」以上であるか判定する。分岐点判定164eの判定結果が真である場合、個別判定164kにジャンプする。分岐点判定164eの判定結果が偽である場合、個別判定164mにジャンプする。分岐点判定164c,164d,164eの判定方法は、二分探索アルゴリズムに相当する。
個別判定164fの判定結果が真である場合、処理Yにジャンプする。個別判定164fの判定結果が偽である場合、個別判定164gに進む。個別判定164gの判定結果が真である場合、処理Yにジャンプする。個別判定164gの判定結果が偽である場合、変数cの値が「13」未満であることが判定済みであり「9」,「10」以外の比較値と一致することがないため、処理Xにジャンプすることが可能である。
個別判定164hの判定結果が真である場合、処理Yにジャンプする。個別判定164hの判定結果が偽である場合、個別判定164iに進む。個別判定164iの判定結果が真である場合、処理Yにジャンプする。個別判定164iの判定結果が偽である場合、個別判定164jに進む。個別判定164jの判定結果が真である場合、処理Yにジャンプする。個別判定164jの判定結果が偽である場合、変数cの値が「13」以上「39」未満であることが判定済みであり「13」,「32」,「34」以外の比較値と一致することがないため、処理Xにジャンプすることが可能である。
個別判定164kの判定結果が真である場合、処理Yにジャンプする。個別判定164kの判定結果が偽である場合、個別判定164lに進む。個別判定164lの判定結果が真である場合、処理Yにジャンプする。個別判定164lの判定結果が偽である場合、変数cの値が「39」以上「59」未満であることが判定済みであり「39」,「47」以外の比較値と一致することがないため、処理Xにジャンプすることが可能である。
個別判定164mの判定結果が真である場合、処理Yにジャンプする。個別判定164mの判定結果が偽である場合、個別判定164nに進む。個別判定164nの判定結果が真である場合、処理Yにジャンプする。個別判定164nの判定結果が偽である場合、個別判定164oに進む。個別判定164oの判定結果が真である場合、処理Yにジャンプする。個別判定164oの判定結果が偽である場合、変数cの値が「59」以上であることが判定済みであり「59」,「123」,「125」以外の比較値と一致することがないため、処理Xにジャンプすることが可能である。
なお、分岐点判定164c以降の判定方法は、逐次的に実行される個別判定が含まれているため、純粋な二分探索アルゴリズムとは異なる。この点で、分岐点判定164c以降の判定方法は、準二分探索アルゴリズムと言うこともできる。
図11は、最適化されたプログラムの例を示す図である。
マシン依存最適化部145は、図10に示した制御構造を表すように前述のブロック情報を更新する。マシン依存最適化部145は、更新したブロック情報に基づいて中間コードを書き換える。コード165は、コード163を最適化したものである。図11では、コード165を疑似アセンブラ形式で記述している。
コード165では、他のブロックと比較する変数が異なるラベルL5のブロックが、先頭に移動している。ラベルL5のブロックの次に、ラベルL14,L15のブロックが挿入されている。ラベルL14,L15のブロックは、境界判定164aに対応する。ラベルL14では、変数cの値が「9」より小さいか判定し、判定結果が真の場合にラベルL12にジャンプする。ラベルL15では、変数cの値が「125」より大きいか判定し、判定結果が真の場合にラベルL12にジャンプする。
ラベルL15のブロックの次に、ラベルL16,L17のブロックが挿入されている。ラベルL16,L17のブロックは、隙間判定164bに対応する。ラベルL16では、変数cの値が「60」より小さいか判定し、判定結果が真の場合にラベルL18にジャンプする。ラベルL17では、変数cの値が「123」より小さいか判定し、判定結果が真の場合にラベルL12にジャンプする。
ラベルL17のブロックの次に、ラベルL18のブロックが挿入されている。ラベルL18のブロックは、分岐点判定164cに対応する。ラベルL18では、変数cの値が「39」以上か判定し、判定結果が真の場合にラベルL20にジャンプする。ラベルL18のブロックの次に、ラベルL19のブロックが挿入されている。ラベルL19のブロックは、分岐点判定164dに対応する。ラベルL19では、変数cの値が「13」以上か判定し、判定結果が真の場合にラベルL4にジャンプする。
ラベルL1〜11のブロックは、比較値の昇順にソートされている。ラベルL19のブロックの次に、ラベルL3のブロックが配置されている。ラベルL3のブロックは、個別判定164fに対応する。ラベルL3のブロックの次に、ラベルL1のブロックが配置されている。ラベルL1のブロックは、個別判定164gに対応する。ラベルL1のブロックの末尾には、ラベルL12にジャンプするba命令が挿入されている。
ラベルL1のブロックの次に、ラベルL4のブロックが配置されている。ラベルL4のブロックは、個別判定164hに対応する。ラベルL4のブロックの次に、ラベルL2のブロックが配置されている。ラベルL2のブロックは、個別判定164iに対応する。ラベルL2のブロックの次に、ラベルL6のブロックが配置されている。ラベルL6のブロックは、個別判定164jに対応する。ラベルL6のブロックの末尾には、ラベルL12にジャンプするba命令が挿入されている。
ラベルL6のブロックの次に、ラベルL20のブロックが挿入されている。ラベルL20のブロックは、分岐点判定164eに対応する。ラベルL20では、変数cの値が「59」以上か判定し、判定結果が真の場合にラベルL9にジャンプする。ラベルL20のブロックの次に、ラベルL7のブロックが配置されている。ラベルL7のブロックは、個別判定164kに対応する。ラベルL7のブロックの次に、ラベルL8のブロックが配置されている。ラベルL8のブロックは、個別判定164lに対応する。ラベルL8のブロックの末尾には、ラベルL12にジャンプするba命令が挿入されている。
ラベルL8のブロックの次に、ラベルL9のブロックが配置されている。ラベルL9のブロックは、個別判定164mに対応する。ラベルL9のブロックの次に、ラベルL10のブロックが配置されている。ラベルL10のブロックは、個別判定164nに対応する。ラベルL10のブロックの次に、ラベルL11のブロックが配置されている。ラベルL11のブロックは、個別判定164oに対応する。そして、ラベルL11のブロックの次に、ラベルL12,L13のブロックが配置されている。このように、最適化されたコード165は、図10に示した制御構造をもっている。
次に、コンパイラ131のコンパイル手順について説明する。
図12は、コンパイルの手順例を示すフローチャートである。
(S1)ソースコード入力部132は、ソースコード記憶部121からソースコードを読み出す。中間コード生成部133は、読み出されたソースコードを解析し、ソースコードを中間コードに変換して中間コード記憶部122に格納する。ソースコードの解析には、字句解析、構文解析、意味解析などのフロントエンド処理が含まれる。
(S2)最適化部134の汎用最適化部141は、中間コード記憶部122に記憶された中間コードに対して、汎用的な最適化を実行する。汎用的な最適化には、使用されていない変数の削除、静的に決定できる値のみに依存する計算式の定数化、複数の計算式に共通に含まれる部分式の計算結果の再利用などが含まれる。
(S3)最適化部134のループ最適化部142は、中間コード記憶部122に記憶された中間コードからループを検出し、ループの最適化を実行する。ループの最適化には、ループ内で値が変わらない変数に関する演算をループ外に移動することや、ループ内の命令を展開(アンローリング)して、ループの繰り返し数を減らすことなどが含まれる。
(S4)最適化部134のSIMD最適化部143は、中間コード記憶部122に記憶された中間コードに対して、SIMD命令を用いた最適化を行う。すなわち、SIMD最適化部143は、中間コードの中から依存関係がなく演算の種類が同じスカラ命令の組を検出し、検出したスカラ命令の組をSIMD命令に変換する。
(S5)最適化部134の命令変換部144は、中間コード記憶部122に記憶された中間コードで使用されている命令形式を、ターゲットのCPUアーキテクチャがサポートする命令セットの命令形式に変換する。コンパイルコマンドのオプションなどによってユーザからターゲットのCPUアーキテクチャが指定された場合、命令変換部144は、中間コードの命令を指定されたCPUアーキテクチャの命令形式に変換する。
(S6)最適化部134のマシン依存最適化部145は、CPU依存の命令の種類を活用した最適化を行う。マシン依存最適化部145は特に、1つの変数の値と複数の比較値とを比較し比較結果に応じて処理が分岐する制御構造を最適化する。以下では、このような制御構造を最適化するマシン依存最適化を中心に説明する。
(S7)最適化部134の命令スケジューリング部148は、中間コード記憶部122に記憶された中間コードに対して命令のスケジューリングを行う。スケジューリングには、命令の並列化や、パイプライン処理を考慮した命令の順序の入れ替えなどが含まれる。
(S8)アセンブリコード生成部135は、中間コード記憶部122から最適化後の中間コードを読み出し、中間コードからアセンブリコードを生成する。
(S9)オブジェクトコード出力部136は、ステップS8で生成されたアセンブリコードをオブジェクトコードに変換し、オブジェクトコード記憶部123に格納する。生成されたオブジェクトコードは、リンカ137によって他のオブジェクトコードやライブラリとリンクされ、実行ファイルに変換されることになる。
図13は、マシン依存最適化の手順例を示すフローチャートである。
マシン依存最適化は、前述のステップS6で実行される。
(S10)解析部146は、中間コードの中の最初の命令を命令iとして選択する。
(S11)解析部146は、命令iとして選択する命令が存在しないか(命令iがNULLであるか)判断する。命令iがNULLである場合はマシン依存最適化が終了する。命令iがNULLでない場合はステップS12に処理が進む。
(S12)解析部146は、命令iが比較命令(cmp命令)であるか判断する。命令iが比較命令である場合はステップS14に処理が進み、命令iが比較命令でない場合はステップS13に処理が進む。
(S13)解析部146は、現在の命令iの次の命令を新たな命令iとして選択する。そして、ステップS11に処理が進む。
(S14)解析部146は、命令iの次の命令を命令jとして選択する。
(S15)解析部146は、命令jが分岐命令(beq命令やbne命令など)であるか判断する。命令jが分岐命令である場合はステップS17に処理が進み、命令jが分岐命令でない場合はステップS16に処理が進む。
(S16)解析部146は、命令jの次の命令を新たな命令iとして選択する。そして、ステップS11に処理が進む。
(S17)解析部146は、命令iから始まる一連の比較処理および分岐処理を中間コードの中から検出し、検出した一連の比較処理および分岐処理についてのブロック情報を生成する。ブロック情報生成の詳細は後述する。
(S18)解析部146は、ステップS17で生成したブロック情報に基づいて比較値ベクトル153を生成し、比較値ベクトル153に基づいて間隔マップ154を生成する。ベクトル・マップ生成の詳細は後述する。
(S19)解析部146は、ステップS18で生成した間隔マップ154に基づいて、制御構造を変更した場合の比較パターン数を、隙間判定の個数を変化させながら試算する。解析部146は、比較パターン数が最小になる隙間判定の個数とそのときの比較パターン数を特定する。また、解析部146は、制御構造を変更しない場合の比較パターン数を試算する。解析部146は、制御構造を変更する前後の比較パターン数を比べ、制御構造を変更することで実行効率が改善されるか判定する。効率評価の詳細は後述する。
(S20)ステップS19で効率改善ありと判定された場合、ステップS22に処理が進む。効率改善ありと判定されなかった場合、ステップS21に処理が進む。
(S21)解析部146は、ステップS17で生成したブロック情報と、ステップS18で生成した比較値ベクトル153および間隔マップ154を、制御情報記憶部125から消去する。そして、ステップS11に処理が進む。
(S22)変換部147は、個別判定164f,164g,164h,164i,164j,164k,164l,164m,164n,164oに先行して、境界判定164aおよび隙間判定164bが実行されるように、ブロック情報の追加および更新を行う。先行判定追加の詳細は後述する。
(S23)変換部147は、境界判定164aおよび隙間判定164bの後、分岐点判定164c,164d,164eが実行されるように、ブロック情報の追加および更新を行う。また、変換部147は、個別判定164f,164g,164h,164i,164j,164k,164l,164m,164n,164oの比較処理が、二分探索木に準じた制御構造をもつようにブロック情報の更新を行う。探索木変換の詳細は後述する。
(S24)変換部147は、ステップS22,S23で更新されたブロック情報に基づいて中間コードを書き換える。そして、ステップS11に処理が進む。
図14は、ブロック情報生成の手順例を示すフローチャートである。
ブロック情報生成は、前述のステップS17で実行される。
(S30)解析部146は、命令iの第1オペランドを変数cとして抽出する。また、解析部146は、命令jのオペランドをジャンプ先labelとして抽出する。
(S31)解析部146は、命令iとして選択する命令が存在しないか(命令iがNULLであるか)判断する。命令iがNULLである場合はブロック情報生成が終了する。命令iがNULLでない場合はステップS32に処理が進む。
(S32)解析部146は、命令iが比較命令(cmp命令)であるか判断する。命令iが比較命令である場合はステップS33に処理が進み、命令iが比較命令でない場合はステップS38に処理が進む。
(S33)解析部146は、命令iの第1オペランドがステップS30で抽出した変数cと同じか判断する。命令iの第1オペランドが変数cと同じ場合はステップS34に処理が進み、異なる場合はステップS38に処理が進む。
(S34)解析部146は、命令iの次の命令を命令jとして選択する。
(S35)解析部146は、命令jとして選択する命令が存在しないか(命令jがNULLであるか)判断する。命令jがNULLである場合はステップS44に処理が進む。命令jがNULLでない場合はステップS36に処理が進む。
(S36)解析部146は、命令jが分岐命令(beq命令やbne命令など)であるか判断する。命令jが分岐命令である場合はステップS37に処理が進み、命令jが分岐命令でない場合はステップS44に処理が進む。
(S37)解析部146は、命令jのオペランドがステップS30で抽出したジャンプ先labelと同じか判断する。命令jのオペランドがジャンプ先labelと同じ場合はステップS42に処理が進み、異なる場合はステップS44に処理が進む。
(S38)解析部146は、命令iが属するブロックの末尾が分岐命令であるか判断する。末尾が分岐命令である場合はステップS39に処理が進み、末尾が分岐命令でない場合はステップS44に処理が進む。
(S39)解析部146は、命令iが属するブロックの末尾の分岐命令のオペランドが、ステップS30で抽出したジャンプ先labelと同じか判断する。末尾の分岐命令のオペランドがジャンプ先labelと同じ場合はステップS40に処理が進み、異なる場合はステップS44に処理が進む。
(S40)解析部146は、命令iが属するブロック内に比較命令が存在するか判断する。比較命令が存在する場合はステップS41に処理が進み、比較命令が存在しない場合はステップS44に処理が進む。
(S41)解析部146は、現在の命令iが属するブロック内の比較命令を新たな命令iとして選択する。また、解析部146は、命令iが属するブロックの末尾にある分岐命令を新たな命令jとして選択する。
(S42)解析部146は、命令i,jに基づいて、命令i,jが属するブロックに対応するブロック情報を生成する。ブロック名(項目#A)は、当該ブロックのラベルである。比較値(項目#B)は、命令iの第2オペランドである。境界フラグ(項目#C)、隙間フラグ(項目#D)および分岐点フラグ(項目#E)は、falseである。連続フラグ(項目#F)は、ステップS41を経由していない場合はtrue、ステップS41を経由した場合はfalseである。真ブロック(項目#G)は、命令jのオペランドである。偽ブロック(項目#H)は、当該ブロックの次のブロックのラベルである。
blフラグ(項目#I)、bgフラグ(項目#J)、bgeフラグ(項目#K)およびbaフラグ(項目#L)は、falseである。前ポインタ(項目#M)は、当該ブロックの前のブロックのラベルである。ただし、前のブロックがない場合、前ポインタはNULLである。次ポインタ(項目#N)は、当該ブロックの次のブロックのラベルである。
(S43)解析部146は、現在の命令jの次の命令を新たな命令iとして選択する。また、解析部146は、新たな命令iの次の命令を新たな命令jとして選択する。そして、ステップS31に処理が進む。
(S44)解析部146は、末尾のブロック情報を生成する。末尾のブロック情報のブロック名(項目#A)は、命令iが属するブロック(一連の比較処理および分岐処理を行うブロック群の次のブロック)のラベルである。連続フラグ(項目#F)は、falseである。前ポインタ(項目#M)は、当該ブロックの前のブロックのラベルである。次ポインタ(項目#N)は、NULLである。他の項目は空欄でもよい。
図15は、ベクトル・マップ生成の手順例を示すフローチャートである。
ベクトル・マップ生成は、前述のステップS18で実行される。
(S50)解析部146は、比較値ベクトル153を生成する。
(S51)解析部146は、先頭のブロック情報をブロック情報bとして選択する。
(S52)解析部146は、ブロック情報bの次ポインタ(項目#N)がNULLであるか判断する。次ポインタがNULLである場合はステップS56に処理が進み、次ポインタがNULLでない場合はステップS53に処理が進む。
(S53)解析部146は、ブロック情報bの連続フラグ(項目#F)がtrueであるか判断する。連続フラグがtrueである場合はステップS54に処理が進み、連続フラグがfalseである場合はステップS55に処理が進む。
(S54)解析部146は、ブロック情報bの比較値(項目#B)を比較値ベクトル153に追加する。
(S55)解析部146は、ブロック情報bの次ポインタ(項目#N)が示すブロック情報を次のブロック情報bとして選択する。そして、ステップS52に処理が進む。
(S56)解析部146は、比較値ベクトル153の比較値を昇順にソートする。
(S57)解析部146は、インデックスpに0を代入する。
(S58)解析部146は、インデックスpが、比較値ベクトル153のサイズから1を引いた値より小さいか判断する。上記条件を満たす場合はステップS59に処理が進み、満たさない場合はステップS63に処理が進む。
(S59)解析部146は、比較値ベクトル153からインデックスpが示す比較値とインデックスp+1が示す比較値とを取得する。解析部146は、間隔difとして、インデックスp+1の比較値からインデックスpの比較値を引き1を引いた値を算出する。
(S60)解析部146は、間隔difが0より大きいか判断する。上記条件を満たす場合はステップS61に処理が進み、満たさない場合はステップS62に処理が進む。
(S61)解析部146は、間隔difとインデックスpの比較値とを対応付けて、間隔マップ154に追加する。間隔difは、間隔マップ154のキーに相当する。
(S62)解析部146は、インデックスpに1を加算する(インデックスpをインクリメントする)。そして、ステップS58に処理が進む。
(S63)解析部146は、間隔マップ154の間隔の降順にソートする。
図16は、効率評価の手順例を示すフローチャートである。
効率評価は、前述のステップS19で実行される。
(S70)解析部146は、区間数xに0を代入する。また、解析部146は、変換後の制御構造の比較パターン数を示す評価値afterに、整数型の最大値を代入する。例えば、解析部146は、評価値afterに、符号なしlong(unsigned long)型整数の最大値である4294967295を代入する。
(S71)解析部146は、区間数xが間隔マップ154のサイズより小さいか判断する。区間数xが間隔マップ154のサイズより小さい場合はステップS72に処理が進み、それ以外の場合はステップS77に処理が進む。
(S72)解析部146は、間隔マップ154が示す比較値の間の区間のうち、x個の区間について隙間判定を行うと仮定する。このとき、解析部146は、間隔が大きい方から優先的にx個の区間を選択するようにする。
(S73)解析部146は、変換後の制御構造の比較パターン数であって、x個の区間について隙間判定を行う場合の比較パターン数を算出する。
ここで、kを比較値の個数(比較値ベクトル153のサイズ)とする。図7の例の場合、k=10である。dを二分木の深さとする。二分木の深さは、分岐点判定の段数に相当し、図10の例ではd=2である。dの値は予め決められていてもよいし、比較値の数に応じて可変としてもよい。また、Kmaxを変数cの型の最大値、Kminを変数cの型の最小値とする。図7の例の場合、変数cはchar型であるため、Kmax=127,Kmin=−128である。また、kmaxを比較値の最大値、kminを比較値の最小値とする。図7の例の場合、kmax=125,kmin=9である。
また、P=Kmax−Kmin+1,K=kmax−kmin+1,m=k/2dの商,n=k/2dの余りとする。図7の例の場合、P=256,K=117,m=2,n=2である。また、wを、間隔マップ154に登録された間隔を降順にソートした配列とする。
解析部146は、上記のパラメータの値を数式(1)に代入することで、変換後の制御構造の比較パターン数を算出することができる。数式(1)によって算出される比較パターン数は、変数cが取り得る全ての整数が入力されたときの比較回数の合計を示す。なお、t,y,zは数式内で値が変化する一時的な変数である。
数式(1)の第1項は、境界判定で行われる比較の回数を示す。数式(1)の第2項は、境界判定の判定結果が偽になった整数について、隙間判定で行われる比較の回数を示す。隙間判定およびそれ以降の判定処理の比較回数は、区間数xに依存する。数式(1)の第3項は、隙間判定の判定結果が偽になった整数について、分岐点判定で行われる比較の回数を示す。数式(1)の第4項は、個別判定のうち全経路に共通の深さまでの個別判定で行われる比較の回数を示す。図10の例の場合、全経路に共通の個別判定の深さは2であり、第4項は、個別判定164f,164g,164h,164i,164k,164l,164m,164nの比較回数を示す。数式(1)の第5項は、残りの個別判定で行われる比較の回数を示す。図10の例の場合、第5項は、第4項でカウントされなかった個別判定164j,164oの比較回数を示す。
(S74)解析部146は、ステップS73で算出された比較パターン数が評価値afterより小さいか判断する。算出された比較パターン数が評価値afterより小さい場合、ステップS75に処理が進む。算出された比較パターン数が評価値after以上である場合、ステップS76に処理が進む。
(S75)解析部146は、ステップS73で算出された比較パターン数を評価値afterに代入し、更新した評価値afterと対応付けて区間数xを記憶しておく。
(S76)解析部146は、区間数xに1を加算する(区間数xをインクリメントする)。そして、ステップS71に処理が進む。以上のステップS71〜S76によって、評価値afterが最小になる区間数xとそのときの評価値afterが決定される。
なお、図7の例の場合、区間数x=0に対応する比較パターン数は512+234+230+54=1030である。区間数x=1に対応する比較パターン数は512+234+108+104+23=981である。区間数x=2に対応する比較パターン数は512+342+72+68+14=1008である。区間数x=3に対応する比較パターン数は512+414+50+46+8=1030である。区間数x=4に対応する比較パターン数は512+464+36+32+5=1049である。区間数x=5に対応する比較パターン数は512+500+28+24+3=1067である。区間数x=6に対応する比較パターン数は512+528+24+20+2=1086である。
以上から、評価値after=981,区間数x=2と決定される。上記のように、区間数xを増やすと、分岐点判定や個別判定に到達する整数が少なくなり、分岐点判定や個別判定の比較回数を削減することができる。一方で、区間数xを増やすと、隙間判定自体の比較回数が増加する。そのため、評価値afterを最小にする区間数xは、0(隙間判定なし)と最大値(全区間について隙間判定あり)の間になることがある。
(S77)解析部146は、変換前の制御構造の比較パターン数を算出し、算出された比較パターン数を評価値beforeに代入する。変換前の制御構造の比較パターン数は、上記のP,kを数式(2)に代入することで算出できる。数式(2)によって算出される比較パターン数は、変数cが取り得る全ての整数が入力されたときの比較回数の合計を示す。なお、yは数式内で値が変化する一時的な変数である。
(S78)解析部146は、評価値afterが評価値beforeよりも小さいか判断する(after<before)。評価値afterが評価値beforeよりも小さい場合はステップS79に処理が進み、評価値afterが評価値before以上である場合はステップS80に処理が進む。
(S79)解析部146は、制御構造を変換することで実行効率が改善する(効率改善あり)と判定する。そして、効率評価が終了する。
(S80)解析部146は、制御構造を変換しても実行効率は改善しない(効率改善なし)と判定する。なお、評価値afterが評価値beforeより小さい場合であっても、両者の差が閾値未満である場合には効率改善なしと判定するようにしてもよい。
図17は、先行判定追加の手順例を示すフローチャートである。
先行判定追加は、前述のステップS22で実行される。
(S110)変換部147は、先頭のブロック情報をブロック情報bとして選択する。
(S111)変換部147は、ブロック情報bの次ポインタ(項目#N)がNULLであるか判断する。次ポインタがNULLである場合はステップS115に処理が進み、次ポインタがNULLでない場合はステップS112に処理が進む。
(S112)変換部147は、ブロック情報bの連続フラグ(項目#F)がtrueであるか判断する。連続フラグがtrueである場合はステップS114に処理が進み、連続フラグがfalseである場合はステップS113に処理が進む。
(S113)変換部147は、ブロック情報bを先頭に移動する。すなわち、変換部147は、ブロック情報bの前ポインタ(項目#M)をNULLに更新し、ブロック情報bの次ポインタ(項目#N)を元の先頭のブロック情報のブロック名(項目#A)に更新する。また、変換部147は、元の先頭のブロック情報の前ポインタ(項目#M)、ブロック情報bの前のブロック情報の次ポインタ(項目#N)、ブロック情報bの後ろのブロック情報の前ポインタ(項目#M)に、順序変更を反映させる。
(S114)変換部147は、ブロック情報bの次ポインタ(項目#N)が示すブロック情報を次のブロック情報bとして選択する。ただし、ステップS113でブロック情報bを移動した場合には、変換部147は、移動前の次ポインタ(項目#N)が示すブロック情報を選択する。そして、ステップS111に処理が進む。
(S115)変換部147は、先頭のブロック情報をブロック情報bとして選択する。
(S116)変換部147は、ブロック情報bの次ポインタ(項目#N)がNULLであるか判断する。次ポインタがNULLである場合はステップS121に処理が進み、次ポインタがNULLでない場合はステップS117に処理が進む。
(S117)変換部147は、ブロック情報bの連続フラグ(項目#F)がtrueであるか判断する。連続フラグがtrueである場合はステップS119に処理が進み、連続フラグがfalseである場合はステップS118に処理が進む。
(S118)変換部147は、ブロック情報bの次ポインタ(項目#N)が示すブロック情報を次のブロック情報bとして選択する。そして、ステップS116に処理が進む。
(S119)変換部147は、ブロック情報bの前に新たなブロック情報を追加する。ここで追加するブロック情報は、境界判定において変数cの値と比較値の最小値(下限境界)とを比較するブロックのブロック情報である。
ブロック名(項目#A)は、既存のラベルと重複しない新たなラベルである。比較値(項目#B)は、最小の比較値(kmin)である。境界フラグ(項目#C)は、trueである。隙間フラグ(項目#D)、分岐点フラグ(項目#E)および連続フラグ(項目#F)は、falseである。真ブロック(項目#G)は、末尾のブロック情報のブロック名である。偽ブロック(項目#H)は、以下のステップS120で追加されるブロック情報のブロック名である。blフラグ(項目#I)は、trueである。bgフラグ(項目#J)、bgeフラグ(項目#K)およびbaフラグ(項目#L)は、falseである。前ポインタ(項目#M)は、1つ前のブロック情報のブロック名である。次ポインタ(項目#N)は、ステップS120で追加されるブロック情報のブロック名である。また、1つ前のブロック情報の次ポインタ(項目#N)を更新する。
(S120)変換部147は、ステップS119のブロック情報の次に、新たなブロック情報を追加する。ここで追加するブロック情報は、境界判定において変数cの値と比較値の最大値(上限境界)とを比較するブロックのブロック情報である。
ブロック名(項目#A)は、既存のラベルと重複しない新たなラベルである。比較値(項目#B)は、最大の比較値(kmax)である。境界フラグ(項目#C)は、trueである。隙間フラグ(項目#D)、分岐点フラグ(項目#E)および連続フラグ(項目#F)は、falseである。真ブロック(項目#G)は、末尾のブロック情報のブロック名である。偽ブロック(項目#H)は、ブロック情報bのブロック名である。bgフラグ(項目#J)は、trueである。blフラグ(項目#I)、bgeフラグ(項目#K)およびbaフラグ(項目#L)は、falseである。前ポインタ(項目#M)は、ステップS119で追加したブロック情報のブロック名である。次ポインタ(項目#N)は、ブロック情報bのブロック名である。変換部147は、ブロック情報bの前ポインタ(項目#M)を更新する。そして、ステップS121に処理が進む。
図18は、先行判定追加の手順例を示すフローチャート(続き)である。
(S121)変換部147は、先頭のブロック情報をブロック情報bとして選択する。
(S122)変換部147は、ブロック情報bの次ポインタ(項目#N)がNULLであるか判断する。次ポインタがNULLである場合、先行判定追加が終了する。次ポインタがNULLでない場合、ステップS123に処理が進む。
(S123)変換部147は、ブロック情報bの境界フラグ(項目#C)がfalse、かつ、連続フラグ(項目#F)がtrueであるか判断する。上記条件を満たす場合はステップS125に処理が進み、満たさない場合はステップS124に処理が進む。
(S124)変換部147は、ブロック情報bの次ポインタ(項目#N)が示すブロック情報を次のブロック情報bとして選択する。そして、ステップS122に処理が進む。
(S125)変換部147は、インデックスpに0を代入する。
(S126)変換部147は、インデックスpが、前述の効率評価で決定された隙間判定の区間数x未満であるか判断する。インデックスpが区間数x未満である場合はステップS127に処理が進み、それ以外の場合は先行判定追加が終了する。
(S127)変換部147は、間隔マップ154からp+1番目の比較値を抽出する。
(S128)変換部147は、ブロック情報bの前に新たなブロック情報を追加する。ここで追加するブロック情報は、隙間判定において変数cの値と隙間の下限とを比較するブロックのブロック情報である。
ブロック名(項目#A)は、既存のラベルと重複しない新たなラベルである。比較値(項目#B)は、ステップS127で抽出した比較値に1を加えた整数である。隙間フラグ(項目#D)は、trueである。境界フラグ(項目#C)、分岐点フラグ(項目#E)および連続フラグ(項目#F)は、falseである。真ブロック(項目#G)は、以下のステップS129で追加されるブロック情報の1つ後ろのブロック情報のブロック名である。偽ブロック(項目#H)は、ステップS129で追加されるブロック情報のブロック名である。blフラグ(項目#I)は、trueである。bgフラグ(項目#J)、bgeフラグ(項目#K)およびbaフラグ(項目#L)は、falseである。前ポインタ(項目#M)は、1つ前のブロック情報のブロック名である。次ポインタ(項目#N)は、ステップS129で追加されるブロック情報のブロック名である。また、1つ前のブロック情報の次ポインタ(項目#N)を更新する。
(S129)変換部147は、ステップS128のブロック情報の次に、新たなブロック情報を追加する。ここで追加するブロック情報は、隙間判定において変数cの値と隙間の上限とを比較するブロックのブロック情報である。
ブロック名(項目#A)は、既存のラベルと重複しない新たなラベルである。比較値(項目#B)は、ステップS127で抽出した比較値より1つ大きい比較値である。隙間フラグ(項目#D)は、trueである。境界フラグ(項目#C)、分岐点フラグ(項目#E)および連続フラグ(項目#F)は、falseである。真ブロック(項目#G)は、末尾のブロック情報のブロック名である。偽ブロック(項目#H)は、1つ後ろのブロック情報のブロック名である。blフラグ(項目#I)は、trueである。bgフラグ(項目#J)、bgeフラグ(項目#K)およびbaフラグ(項目#L)は、falseである。前ポインタ(項目#M)は、ステップS128で追加したブロック情報のブロック名である。次ポインタ(項目#N)は、1つ後ろのブロック情報のブロック名である。1つ後ろのブロック情報の前ポインタ(項目#M)を更新する。また、区間数xが2以上である場合、2以上の区間についての隙間判定が連続的に実行されるように、真ブロック(項目#G)などを適宜更新する。そして、ステップS126に処理が進む。
図19は、ブロック情報の第1の更新例を示す図である。
上記のステップS119において、例えば、ブロック情報152mが追加される。ブロック名(項目#A)は、新たなラベルであるL14である。比較値(項目#B)は、最小の比較値「9」である。境界フラグ(項目#C)は、trueである。真ブロック(項目#G)は、L12である。偽ブロック(項目#H)は、ブロック情報152nを示すL15である。blフラグ(項目#I)は、trueである。前ポインタ(項目#M)は、先頭に移動したL5である。次ポインタ(項目#N)は、L15である。
また、上記のステップS120において、例えば、ブロック情報152nが追加される。ブロック名(項目#A)は、新たなラベルであるL15である。比較値(項目#B)は、最大の比較値「125」である。境界フラグ(項目#C)は、trueである。真ブロック(項目#G)は、L12である。偽ブロック(項目#H)は、ブロック情報152oを示すL16である。bgフラグ(項目#J)は、trueである。前ポインタ(項目#M)は、L14である。次ポインタ(項目#N)は、L16である。なお、ブロック情報152m,152nは、境界判定164aに対応する。
また、上記のステップS128において、例えば、ブロック情報152oが追加される。ブロック名(項目#A)は、新たなラベルであるL16である。比較値(項目#B)は、間隔マップ154の1番目の比較値に1を加えた「60」である。隙間フラグ(項目#D)は、trueである。真ブロック(項目#G)は、ブロック情報152pの後ろのブロック情報152aを示すL1である。偽ブロック(項目#H)は、ブロック情報152pを示すL17である。blフラグ(項目#I)は、trueである。前ポインタ(項目#M)は、L15である。次ポインタ(項目#N)は、L17である。
また、上記のステップS129において、例えば、ブロック情報152pが追加される。ブロック名(項目#A)は、新たなラベルであるL17である。比較値(項目#B)は、間隔マップ154の1番目の比較値より1つ大きい比較値である「123」である。隙間フラグ(項目#D)は、trueである。真ブロック(項目#G)は、L12である。偽ブロック(項目#H)は、L1である。blフラグ(項目#I)は、trueである。前ポインタ(項目#M)は、L16である。次ポインタ(項目#N)は、L1である。なお、ブロック情報152o,152pは、隙間判定164bに対応する。
図20は、探索木変換の手順例を示すフローチャートである。
探索木変換は、前述のステップS23で実行される。
(S130)変換部147は、変数qに1を代入する。
(S131)変換部147は、変数qの値が二分木の高さd以下であるか判断する。高さdは予め与えられていてもよいし、比較値の個数から決定してもよい。変数qの値が高さd以下である場合はステップS132に処理が進み、変数qの値が高さdを超える場合はステップS138に処理が進む。
(S132)変換部147は、変数rに1を代入する。
(S133)変換部147は、変数rの値が変数qの値以下であるか判断する。変数rの値が変数qの値以下である場合はステップS135に処理が進み、変数rの値が変数qの値を超える場合はステップS134に処理が進む。
(S134)変換部147は、変数qの値に1を加える(変数qをインクリメントする)。そして、ステップS131に処理が進む。
(S135)変換部147は、インデックスp=k/2q×(2r−1)を算出する。kは、比較値の個数、すなわち、比較値ベクトル153のサイズである。上記の式でインデックスpの値が非整数になった場合、最終的な計算結果の小数点以下を切り捨てる。例えば、k=10,q=2,r=2の場合、p=10/4×3=30/4=7となる。
(S136)変換部147は、比較値ベクトル153からインデックスpの比較値とインデックスp−1の比較値を取得する。変換部147は、インデックスpの比較値とbge命令とを対応付けて命令テーブル155に追加する。また、変換部147は、インデックスp−1の比較値とba命令とを対応付けて命令テーブル155に追加する。
(S137)変換部147は、変数rの値に1を加える(変数rをインクリメントする)。そして、ステップS133に処理が進む。
(S138)変換部147は、先頭のブロック情報をブロック情報bとして選択する。
(S139)変換部147は、ブロック情報bの境界フラグ(項目#C)がfalse、隙間フラグ(項目#D)がfalse、かつ、連続フラグ(項目#F)がtrueであるか判断する。上記条件を満たす場合はステップS141に処理が進み、満たさない場合はステップS140に処理が進む。
(S140)変換部147は、ブロック情報bの次ポインタ(項目#N)が示すブロック情報を次のブロック情報bとして選択する。そして、ステップS139に処理が進む。
(S141)変換部147は、ブロック情報bおよびそれより後ろのブロック情報を、比較値の昇順にソートする。例えば、図7の例の場合、ラベルL1〜L11を、ラベルL3,L1,L4,L2,L6,L7〜L11の順にソートする。
(S142)変換部147は、命令テーブル155に基づいてブロック情報の追加や更新を行う。具体的には、変換部147は、命令テーブル155から命令種類がbgeである比較値を検索し、検索した比較値それぞれに対応するブロック情報を追加する。ここで追加するブロック情報は、分岐点判定を示すブロックのブロック情報である。
ブロック名(項目#A)は、既存のラベルと重複しない新たなラベルである。比較値(項目#B)は、命令テーブル155から検索した比較値である。分岐点フラグ(項目#E)は、trueである。境界フラグ(項目#C)、隙間フラグ(項目#D)および連続フラグ(項目#F)は、falseである。bgeフラグ(項目#K)は、trueである。blフラグ(項目#I)、bgフラグ(項目#J)およびbaフラグ(項目#L)は、falseである。このブロック情報は、二分探索が実現される位置に挿入される。真ブロック(項目#G)、偽ブロック(項目#H)、前ポインタ(項目#M)および次ポインタ(項目#N)は、挿入された位置に応じた適切なラベルとなる。偽ブロック(項目#H)のラベルと次ポインタ(項目#N)のラベルは一致する。
また、変換部147は、命令テーブル155から命令種類がbaである比較値を検索し、検索した比較値を含むブロック情報を検索する。変換部147は、検索したブロック情報のbaフラグ(項目#L)をtrueに変更する。また、変換部147は、検索したブロック情報の偽ブロック(項目#H)を末尾のブロック情報のラベルに変更する。
図21は、ブロック情報の第2の更新例を示す図である。
上記のステップS142において、例えば、ブロック情報152q,152r,152sが追加される。ブロック情報152qは、命令テーブル155の比較値「39」に対応し、分岐点判定164cに対応する。ブロック情報152rは、命令テーブル155の比較値「13」に対応し、分岐点判定164dに対応する。ブロック情報152sは、命令テーブル155の比較値「59」に対応し、分岐点判定164eに対応する。
ブロック情報152qについて、ブロック名(項目#A)は、新たなラベルであるL18である。比較値(項目#B)は、命令テーブル155から検索された「39」である。分岐点フラグ(項目#E)は、trueである。真ブロック(項目#G)は、ブロック情報152sを示すL20である。偽ブロック(項目#H)は、ブロック情報152rを示すL19である。bgeフラグ(項目#K)は、trueである。前ポインタ(項目#M)は、L17である。次ポインタ(項目#N)は、L19である。
ブロック情報152rについて、ブロック名(項目#A)は、L19である。比較値(項目#B)は、命令テーブル155から検索された「13」である。分岐点フラグ(項目#E)は、trueである。真ブロック(項目#G)は、L4である。偽ブロック(項目#H)は、L3である。bgeフラグ(項目#K)は、trueである。前ポインタ(項目#M)は、L18である。次ポインタ(項目#N)は、L3である。
ブロック情報152sについて、ブロック名(項目#A)は、L20である。比較値(項目#B)は、命令テーブル155から検索された「59」である。分岐点フラグ(項目#E)は、trueである。真ブロック(項目#G)は、L9である。偽ブロック(項目#H)は、L7である。bgeフラグ(項目#K)は、trueである。前ポインタ(項目#M)は、L6である。次ポインタ(項目#N)は、L7である。
また、上記のステップS142において、例えば、ブロック情報152a,152f,152hが更新される。ブロック情報152a,152f,152hの偽ブロック(項目#H)がL12に変更されている。また、ブロック情報152a,152f,152hのbaフラグ(項目#L)がtrueに変更されている。この他に、上記のステップS141のソートによって、各ブロック情報の偽ブロック(項目#H)、前ポインタ(項目#M)および次ポインタ(項目#N)が適切に変更される。更新された一連のブロック情報を先頭から末尾に向かって辿ることで、例えば、図11のコード165が生成される。
第2の実施の形態のコンパイル装置100によれば、中間コードから、ある変数の値と複数の比較値それぞれとを比較し、変数の値が何れかの比較値と一致するか否かによって処理が分岐する制御構造が検出される。そして、検出された制御構造が、個々の比較値についての個別判定の前に、境界判定、隙間判定および分岐点判定が挿入された別の制御構造に変換される。境界判定では、変数の値が最小の比較値より小さいかまたは最大の比較値より大きい場合に、隙間判定と分岐点判定と全ての個別判定がスキップされる。隙間判定では、変数の値が間隔の広い隣接する2つの比較値の間に属する場合に、分岐点判定と全ての個別判定がスキップされる。分岐点判定では、二分探索アルゴリズムに準じた探索方法によって一部の比較値についての個別判定がスキップされる。
これにより、変数の値1つ当たりの平均の比較回数が削減され、比較処理および分岐処理を効率化できる。例えば、比較値を真になる確率が高い順にソートするだけでは、変数の値が何れの比較値とも一致しない場合、その変数の値と全ての比較値とを比較することになってしまう。また、比較値の間で真になる確率の差が小さい(ばらつきが小さい)場合には、比較回数を削減することが難しい。これに対し、第2の実施の形態の方法では、変数の値が何れの比較値とも一致しない場合でも比較回数を削減することができる。また、コンパイル装置100は、比較結果が真になる確率を収集しなくてもよく、オブジェクトコードをテスト実行するコストやコンパイルのコストを削減することができる。
また、変数の値1つ当たりの平均の比較回数が削減されることで、分岐命令の実行回数が削減される。分岐命令の実行回数を削減することで、オブジェクトコードを実行するプロセッサのパイプライン処理において、分岐予測の失敗により生じる再実行コスト(ペナルティ)を削減できる。よって、オブジェクトコードの実行効率を向上させることができる。また、隙間判定を行う比較値間の区間の個数は、比較パターン数が最小になるように決定される。また、制御構造を変換した後の比較パターン数が変換前よりも少なくなると推定される場合のみ、制御構造の変換が行われる。これにより、実行時の比較回数が一層削減され、比較処理および分岐処理を一層効率化できる。
なお、前述のように、第1の実施の形態の情報処理は、コンパイル装置10にプログラムを実行させることで実現できる。第2の実施の形態の情報処理は、コンパイル装置100にプログラムを実行させることで実現できる。
プログラムは、コンピュータ読み取り可能な記録媒体(例えば、記録媒体113)に記録しておくことができる。記録媒体として、例えば、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、FDおよびHDDが含まれる。光ディスクには、CD、CD−R(Recordable)/RW(Rewritable)、DVDおよびDVD−R/RWが含まれる。プログラムは、可搬型の記録媒体に記録されて配布されることがある。その場合、可搬型の記録媒体から他の記録媒体(例えば、HDD103)にプログラムをコピーして実行してもよい。