(19)【発行国】日本国特許庁(JP)
(12)【公報種別】特許公報(B2)
(11)【特許番号】
(24)【登録日】2023-02-13
(45)【発行日】2023-02-21
(54)【発明の名称】コンパイラ装置、プログラム、及び情報処理方法
(51)【国際特許分類】
G06F 8/41 20180101AFI20230214BHJP
G06F 9/312 20180101ALI20230214BHJP
【FI】
G06F8/41 130
G06F9/312 L
G06F9/312 W
(21)【出願番号】P 2019032032
(22)【出願日】2019-02-25
【審査請求日】2021-11-09
(73)【特許権者】
【識別番号】000005223
【氏名又は名称】富士通株式会社
(74)【代理人】
【識別番号】100087480
【氏名又は名称】片山 修平
(72)【発明者】
【氏名】一場 利幸
【審査官】加藤 優一
(56)【参考文献】
【文献】特開2005-078474(JP,A)
【文献】中林 淳一郎,並列コピーの導入による生存区間分割手法の性能向上,情報処理学会論文誌 論文誌トランザクション 平成20年度 [CD-ROM] ,日本,社団法人情報処理学会,2009年04月30日,第2巻
(58)【調査した分野】(Int.Cl.,DB名)
G06F 8/40-8/54
G06F 9/30-9/355
G06F 9/455
(57)【特許請求の範囲】
【請求項1】
メモリ内の同一のデータを参照する第1のスピル命令と第2のスピル命令とを含む命令列を取得する取得部と、
前記第1のスピル命令と前記第2のスピル命令の各々に第1のレジスタが割付けられている場合であって、前記第1のスピル命令と前記第2のスピル命令との間の第1の区間に前記第1のレジスタが割付けられているときに、前記第1の区間における割付けの変更先の候補となる第2のレジスタを探索する
とともに、前記第2のレジスタが割付けられた第2の区間が第Nのレジスタ(Nは3以上の整数)が割付けられた第Nの区間と重複している場合に、重複しない変更先である第(N+1)のレジスタを再帰的に探索する探索部と、
前記命令列において前記第2のレジスタが割付けられた第2の区間と前記第1の区間とが重複していない場合には、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更し、前記第1の区間と前記第2の区間とが重複している場合には、
前記第Nの区間における割付けを前記第Nのレジスタから前記第(N+1)のレジスタに変更し、前記第2の区間における割付けを前記第2のレジスタから
前記第
Nのレジスタに変更した後に、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更する変更部と、
前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更した後に、前記第1のスピル命令と第2のスピル命令のうち、少なくとも後に実行される命令を削除する削除部と、
を有することを特徴とするコンパイラ装置。
【請求項2】
前記第1のスピル命令と前記第2のスピル命令はスピルイン命令であることを特徴とする請求項1に記載のコンパイラ装置。
【請求項3】
前記命令列は基本ブロックの中にあり、
前記第2の区間が前記基本ブロックの最後まで延びている場合に、前記第2のスピル命令の後に、前記第
Nのレジスタの内容を前記第2のレジスタにコピーするコピー命令を追加する追加部を更に有することを特徴とする請求項1に記載のコンパイラ装置。
【請求項4】
メモリ内の同一のデータを参照する第1のスピル命令と第2のスピル命令とを含む命令列を取得する処理と、
前記第1のスピル命令と前記第2のスピル命令の各々に第1のレジスタが割付けられている場合であって、前記第1のスピル命令と前記第2のスピル命令との間の第1の区間に前記第1のレジスタが割付けられているときに、前記第1の区間における割付けの変更先の候補となる第2のレジスタを探索する
とともに、前記第2のレジスタが割付けられた第2の区間が第Nのレジスタ(Nは3以上の整数)が割付けられた第Nの区間と重複している場合に、重複しない変更先である第(N+1)のレジスタを再帰的に探索する処理と、
前記命令列において前記第2のレジスタが割付けられた第2の区間と前記第1の区間とが重複していない場合には、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更し、前記第1の区間と前記第2の区間とが重複している場合には、
前記第Nの区間における割付けを前記第Nのレジスタから前記第(N+1)のレジスタに変更し、前記第2の区間における割付けを前記第2のレジスタから
前記第
Nのレジスタに変更した後に、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更する処理と、
前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更した後に、前記第1のスピル命令と第2のスピル命令のうち、少なくとも後に実行される命令を削除する処理と、
をコンピュータに実行させるためのプログラム。
【請求項5】
メモリ内の同一のデータを参照する第1のスピル命令と第2のスピル命令とを含む命令列を取得する処理と、
前記第1のスピル命令と前記第2のスピル命令の各々に第1のレジスタが割付けられている場合であって、前記第1のスピル命令と前記第2のスピル命令との間の第1の区間に前記第1のレジスタが割付けられているときに、前記第1の区間における割付けの変更先の候補となる第2のレジスタを探索する
とともに、前記第2のレジスタが割付けられた第2の区間が第Nのレジスタ(Nは3以上の整数)が割付けられた第Nの区間と重複している場合に、重複しない変更先である第(N+1)のレジスタを再帰的に探索する処理と、
前記命令列において前記第2のレジスタが割付けられた第2の区間と前記第1の区間とが重複していない場合には、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更し、前記第1の区間と前記第2の区間とが重複している場合には、
前記第Nの区間における割付けを前記第Nのレジスタから前記第(N+1)のレジスタに変更し、前記第2の区間における割付けを前記第2のレジスタから
前記第
Nのレジスタに変更した後に、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更する処理と、
前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更した後に、前記第1のスピル命令と第2のスピル命令のうち、少なくとも後に実行される命令を削除する処理と、
をコンピュータが実行することを特徴とする情報処理方法。
【発明の詳細な説明】
【技術分野】
【0001】
本発明は、コンパイラ装置、プログラム、及び情報処理方法に関する。
【背景技術】
【0002】
プログラムの実行速度を向上させるためのコンパイラの最適化技法の一つにレジスタ割付けがある。レジスタ割付けは、メモリのデータをレジスタに予め転送しておくことにより、プログラムの実行時におけるメモリアクセスを減らす技法である。メモリアクセスよりもレジスタアクセスの方が速いため、このようにレジスタ割付けを行うことでプログラムの実行速度を向上させることができる。
【0003】
但し、レジスタの個数は限られているため、レジスタに格納しきれないデータについては、スピルアウト命令によってレジスタからメモリに追い出す必要がある。また、メモリに追い出されたデータが必要となった場合には、そのデータを再びレジスタに転送するスピルイン命令を実行する必要がある。スピルアウト命令やスピルイン命令等のスピル命令は、それぞれstore命令やload命令等のメモリ参照命令であるためメモリアクセスに長時間を要し、プログラムの実行速度を低下させてしまう。
【先行技術文献】
【特許文献】
【0004】
【文献】特開2005-107816号公報
【文献】特開2002-312179号公報
【発明の概要】
【発明が解決しようとする課題】
【0005】
一側面によれば、本発明は、プログラムの実行速度を向上させることを目的とする。
【課題を解決するための手段】
【0006】
一側面によれば、メモリ内の同一のデータを参照する第1のスピル命令と第2のスピル命令とを含む命令列を取得する取得部と、前記第1のスピル命令と前記第2のスピル命令の各々に第1のレジスタが割付けられている場合であって、前記第1のスピル命令と前記第2のスピル命令との間の第1の区間に前記第1のレジスタが割付けられているときに、前記第1の区間における割付けの変更先の候補となる第2のレジスタを探索するとともに、前記第2のレジスタが割付けられた第2の区間が第Nのレジスタ(Nは3以上の整数)が割付けられた第Nの区間と重複している場合に、重複しない変更先である第(N+1)のレジスタを再帰的に探索する探索部と、前記命令列において前記第2のレジスタが割付けられた第2の区間と前記第1の区間とが重複していない場合には、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更し、前記第1の区間と前記第2の区間とが重複している場合には、前記第Nの区間における割付けを前記第Nのレジスタから前記第(N+1)のレジスタに変更し、前記第2の区間における割付けを前記第2のレジスタから前記第Nのレジスタに変更した後に、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更する変更部と、前記第1の区間における割付けを前記第1のレジスタから前記第2のレジスタに変更した後に、前記第1のスピル命令と第2のスピル命令のうち、少なくとも後に実行される命令を削除する削除部とを有するコンパイラ装置が提供される。
【発明の効果】
【0007】
一側面によれば、プログラムの実行速度を向上させることができる。
【図面の簡単な説明】
【0008】
【
図1】
図1は、本実施形態に係るターゲットマシンのハードウェア構成図である。
【
図2】
図2は、本実施形態において、基本ブロックにおける命令とレジスタの割付けとを模式的に示す図である。
【
図3】
図3は、本実施形態の第1例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その1)である。
【
図4】
図4は、本実施形態の第1例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その2)である。
【
図5】
図5は、本実施形態の第1例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その3)である。
【
図6】
図6は、本実施形態の第1例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その4)である。
【
図7】
図7は、本実施形態の第1例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その5)である。
【
図8】
図8は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その1)である。
【
図9】
図9は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その2)である。
【
図10】
図10は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その3)である。
【
図11】
図11は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その4)である。
【
図12】
図12は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その5)である。
【
図13】
図13は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その6)である。
【
図14】
図14は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その7)である。
【
図15】
図15は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その8)である。
【
図16】
図16は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その9)である。
【
図17】
図17は、本実施形態の第2例におけるコピー命令と後続の基本ブロックとの関係の一例について示す図である。
【
図18】
図18は、本実施形態の第3例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その1)である。
【
図19】
図19は、本実施形態の第3例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その2)である。
【
図20】
図20は、本実施形態の第3例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その3)である。
【
図21】
図21は、本実施形態の第3例に係るレジスタ割付けの変更方法の概略について模式的に示す図(その4)である。
【
図22】
図22は、本実施形態に係るコンパイラ装置のハードウェア構成図である。
【
図23】
図23は、本実施形態に係るコンパイラ装置の機能について示す機能構成図である。
【
図24】本実施形態に係る情報処理方法について示すフローチャートである。
【
図25】
図25は、本実施形態に係るレジスタ割付けの変更処理について示すフローチャート(その1)である。
【
図26】
図26は、本実施形態に係るレジスタ割付けの変更処理について示すフローチャート(その2)である。
【発明を実施するための形態】
【0009】
(本実施形態)
図1は、本実施形態に係るターゲットマシンのハードウェア構成図である。
【0010】
このターゲットマシン1は、サーバやPC(Personal Computer)等の計算機であって、プロセッサ2とメモリ3とを有する。
【0011】
このうち、プロセッサ2は、算術演算や論理演算を行うALU(Arithmetic and Logic Unit)等の演算部4とレジスタファイル5とを備える。レジスタファイル5は、複数のレジスタを備えたデバイスであって、この例では各レジスタに1番、2番、…と順番に番号を付す。
【0012】
一方、メモリ3は、各種のプログラムが展開されるDRAM(Dynamic Random Access Memory)等の揮発性メモリである。
【0013】
このようなターゲットマシン1でプログラムを実行する場合には、メモリ3におけるデータをスピルイン命令で予めレジスタファイル5に転送しておくことでプログラムの実行速度が向上する。また、プログラムの実行中には、スピルアウト命令によってレジスタファイル5からメモリ3にデータが追い出されることがある。
【0014】
このターゲットマシン1で実行される命令列は、コンパイラがソースコードをコンパイルすることにより出力される。
【0015】
図2は、そのコンパイラによって出力された基本ブロック10における命令とレジスタの割付けとを模式的に示す図である。なお、基本ブロック10は、分岐命令以外の命令を実行順に並べた命令列であり、0番から14番の順に命令が実行される。
【0016】
また、レジスタについては、上から下に向かってレジスタ番号が増えるように並べている。そして、命令に割付け済みのレジスタには斜線やドットのハッチングを掛けてある。なお、ここでは、命令に割付け済みのレジスタは、命令が用いるデータを割付け済みのレジスタのことを指す。また、スピル命令によって転送されるデータを割付けたレジスタに斜線のハッチングを掛け、スピル命令によらないデータを割付けたレジスタにドットのハッチングを掛けてある。また、命令が用いるデータに割り付けられていない空きレジスタは白抜きにしてある。
【0017】
この例では、1番命令、8番命令、及び11番命令がスピルイン命令となっている。スピルイン命令によってレジスタに転送されるデータはメモリ3内のスタック領域で管理される。スタック領域の各データにはスタック番号が割り当てられており、そのスタック番号で各データを一意に識別できる。上記の各スピルイン命令は、いずれもスタック番号が27のデータを2番レジスタに転送するload命令である。
【0018】
メモリアクセスを減らすにはなるべくスピルイン命令を減らすのが好ましい。しかし、この例では、1番のスピルイン命令が実行された後に3番命令と6番命令の各々に2番レジスタが割付けられており、これらの命令によって2番レジスタの内容が書き換えられる可能性がある。よって、3番命令と6番命令の実行が終了した後に、再び8番のスピルイン命令を実行する必要がある。また、コンパイラの最適化が不十分であるため、その後の11番のスピルイン命令が不必要に命令列に含まれてしまっている。
【0019】
プログラムの実行速度を速めるには、8番と11番のスピルイン命令を削除すればよい。そのためには、3番命令と6番命令におけるレジスタの割付け先を2番レジスタから他のレジスタに変更し、区間[2、7]及び区間[9、10]において2番レジスタを割付けないようにすればよい。なお、区間[2、10]は、2番命令から10番命令までの区間である。同様に、以下ではi番命令からj番命令までの区間を[i、j]で表す。
そのようなレジスタ割付けの変更方法について次に説明する。
【0020】
レジスタ割付けの変更は、変更先のレジスタが空いているか否かに応じて異なる方法で行われる。そこで、まず、変更先のレジスタが空いている場合の第1例に係る変更方法について説明する。
【0021】
・第1例
図3~
図7は、本実施形態の第1例に係るレジスタ割付けの変更方法の概略について模式的に示す図である。
【0022】
以下では、
図2のようにレジスタが割付けられている場合を例にして説明する。
【0023】
まず、
図3に示すように、区間[3、3]における2番レジスタの割付けの変更先の候補となるレジスタを探索する。この例では、区間[3、3]において11番レジスタが空いているため、区間[3、3]における2番レジスタの割付けの変更先の候補を11番レジスタとする。なお、以下では、レジスタ割付けの変更元や変更先のレジスタを太い黒枠で示す。
【0024】
次に、
図4に示すように、区間[3、3]におけるレジスタの割付けを2番レジスタから11番レジスタに変更する。
【0025】
そして、上記と同様の探索を区間[6、6]に割付けられた2番レジスタについても行う。区間[6、6]で空いているレジスタは6番レジスタであるため、この例では区間[6、6]における2番レジスタ割付けの変更先の候補を6番レジスタとする。
【0026】
次いで、
図5に示すように、区間[6、6]におけるレジスタの割付けを2番レジスタから6番レジスタに変更する。
【0027】
これにより、
図6に示すように、1番のスピルイン命令に割付けられた2番レジスタのデータが書き換えられずに保持される保持区間を11番命令まで延ばすことができる。よって、8番のスピルイン命令を削除しても、1番のスピルイン命令によって2番レジスタに格納されたデータは11番命令まで変更を受けなくなる。
【0028】
そこで、
図7に示すように、不要な8番のスピルイン命令を削除する。また、コンパイラの不十分な最適化により追加されていた11番のスピルイン命令もここで削除する。
【0029】
これにより、メモリアクセスが必要なスピルイン命令が一つのみになり、かつ基本ブロック10における命令列も短くなるため、プログラムの実行速度を向上させることができる。なお、
図7では、1番のスピルイン命令に割付けられたデータが保持される区間に斜線のハッチングをかけてある。
【0030】
以上説明したように、二つのスピル命令の間の区間にこれらのスピル命令が使用するのと同じレジスタが割付けられている場合に、その区間で他のレジスタが空いているときには、これらのレジスタ間で割付けを変更できる。これにより、二つのスピル命令のうちで後に実行される方を削除してもプログラムの実行結果は変わらず、当該スピル命令を削除してプログラムの実行速度を向上させることが可能となる。
【0031】
但し、変更先のレジスタが割付けられている区間と、変更元のレジスタが割付けられている区間とが重複している場合には、上記の方法では割付けの変更を行うことができない。そこで、次に、各レジスタが割付けられている区間が重複している場合におけるレジスタ割付けの変更方法について説明する。
【0032】
・第2例
図8~
図16は、本実施形態の第2例に係るレジスタ割付けの変更方法の概略について模式的に示す図である。
【0033】
図8の例では、
図3の例と同様に、1番、8番、及び11番の各命令が、メモリ3上でスタック番号が27のデータを2番レジスタに転送するスピルイン命令となっている。但し、区間[3、6]に2番レジスタが割付けられており、2番レジスタが割付けられている区間が
図3のそれよりも長くなっている。
【0034】
この場合は、区間[3、6]の始点で空いているレジスタを探索する。この例では区間[3、6]の始点で11番レジスタが空いているため、その11番レジスタを2番レジスタの割付けの変更先の候補とする。
【0035】
但し、11番レジスタが割付けられている区間は[4、14]であり、2番レジスタが割付けられている区間[3、6]と重複しているため、区間[3、6]における割付けを2番レジスタから11番レジスタに変更することができない。
【0036】
そこで、
図9に示すように、区間[4、14]における割付けを11番レジスタから他のレジスタに変更するため、その変更先の候補を探索する。ここでは、区間[4、14]の始点で空いている10番レジスタを変更先の候補とする。
【0037】
但し、10番レジスタが割付けられている区間は[5、6]であり、11番レジスタが割付けられている区間[4、14]と重複しているため、区間[4、14]における割付けを11番レジスタから10番レジスタに変更することができない。
【0038】
そのため、
図10に示すように、今度は区間[5、6]における割付けを10番レジスタから他のレジスタに変更するため、その変更先の候補を探索する。ここでは、上記と同様に区間[5、6]の始点で空いている9番レジスタを変更先の候補とする。
【0039】
しかし、9番レジスタが割付けられている区間は[6、7]であり、10番レジスタが割付けられている区間[5、6]と重複しているため、区間[5、6]における割付けを10番レジスタから9番レジスタに変更することができない。
【0040】
そこで、更に
図11に示すように、区間[6、7]における割付けを9番レジスタから他のレジスタに変更するために、その変更先の候補を探索する。上記と同様に、ここでも区間[6、7]の始点で空いている6番レジスタを変更先の候補とする。
【0041】
但し、6番レジスタが割付けられている区間は[7、7]であり、9番レジスタが割付けられている区間[6、7]と重複しているため、区間[6、7]における割付けを9番レジスタから6番レジスタに変更することができない。
【0042】
よって、更に
図12に示すように区間[7、7]における割付け先を6番レジスタから他のレジスタに変更するために、その変更先の候補を探索する。ここでは、初めにレジスタ割付けの変更先の探索を行った2番レジスタを除いて、区間[7、7]の始点で空いている5番レジスタを変更先の候補とする。
【0043】
今度は、区間[7、7]の全区間において5番レジスタが空いているため、区間[7、7]における割付けを6番レジスタから5番レジスタに変更することが可能となる。
【0044】
そこで、
図13に示すように、区間[7、7]における割付けを6番レジスタから5番レジスタに変更する(ステップP1)。これにより区間[6、7]の全区間において6番レジスタが空き、区間[6、7]における割付けを9番レジスタから6番レジスタに変更する(ステップP2)。この結果、更に区間[5、6]の全区間において9番レジスタが空き、区間[5、6]における割付けを10番レジスタから9番レジスタに変更する(ステップP3)。
【0045】
同様に、区間[4、14]における割付けを11番レジスタから10番レジスタに変更し(ステップP4)、最後に区間[3、6]における割付けを2番レジスタから11番レジスタに変更する(ステップP5)。
【0046】
以上により、
図14に示すように、1番のスピルイン命令で2番レジスタに転送されたデータが書き換えられずに保持される保持区間が[1、11]となり、その区間内に8番と11番のスピルイン命令が入るようになる。よって、第1例と同様に8番と11番のスピルイン命令を削除でき、プログラムの実行速度を向上することができる。
【0047】
なお、この例では、レジスタ割付けの変更によって11番レジスタの内容が10番レジスタに移っており、この状態が基本ブロック10の最後の14番命令まで継続する。複数の基本ブロックは、各々の最初と最後の命令間でレジスタの割付けを統一することで、プログラムの実行結果の正確性が担保される。例えば、基本ブロックの最後の命令に割付けられたレジスタが後続の基本ブロックの最初の命令にも割付けられていないと、本来使用すべきデータとは異なるデータを利用して後続の基本ブロックが実行されてしまう。
【0048】
これを避けるため、この例では、
図15に示すように、基本ブロック10の最後の15番命令としてコピー命令を追加する。そのコピー命令は、10番レジスタの内容を11番レジスタにコピーする命令である。
【0049】
なお、コピー命令を追加する位置は特に限定されず、コピー先の11番レジスタが割付られていない区間にコピー命令を追加し得る。例えば、6番命令の後にコピー命令を追加することができる。
【0050】
その後に、
図16に示すように、8番と11番の不要なスピルイン命令を削除する。この状態では、基本ブロック10の最後に前述のコピー命令が追加されている。なお、
図16では、1番のスピルイン命令に割付けられたデータが保持される区間に斜線のハッチングをかけてある。
【0051】
図17は、そのコピー命令と後続の基本ブロック11との関係の一例について示す図である。
【0052】
図17に示すように、コピー命令を追加したことにより、基本ブロック10の最後の13番命令と、基本ブロック11の最初の1番命令のそれぞれのレジスタ割付けが一致する。これにより、レジスタ割付けを変更する前と同じレジスタの内容を基本ブロック11の1番命令が使用できるようになり、基本ブロック11の実行結果をレジスタ割付けの変更前と同一にすることができる。
【0053】
以上説明した例では、
図16のように二つのスピルイン命令を削除することで基本ブロック10に含まれる命令数が減り、ターゲットマシン1におけるプログラムの実行速度が向上する。しかも、メモリアクセスを要するスピルイン命令を削除したことでプログラムの実行速度を更に向上することができる。
【0054】
・第3例
前述の第1例と第2例ではスピルイン命令を削除したが、同様の手順でスピルアウト命令も削除することができる。これについて以下に説明する。
【0055】
図18~
図21は、本実施形態の第3例に係るレジスタ割付けの変更方法の概略について模式的に示す図である。
【0056】
図18の例では、0番命令が、0番レジスタの内容をメモリ3に転送するスピルアウト命令となっている。なお、転送先は、メモリ3でスタック番号が10の領域である。また、7番命令は、スタック番号が10のデータを0番レジスタに転送するスピルイン命令である。
【0057】
この場合は、区間[3、5]において0番レジスタが割付けられており、その区間[3、5]で0番レジスタの内容が書き換えられないように0番命令でスピルアウトを行い、0番レジスタのデータをメモリ3に退避させている。そして、区間[3、5]の各命令が終了した後に7番命令でスピルインをすることにより、メモリ3に退避させたデータを再び0番レジスタに転送している。
【0058】
よって、0番のスピルアウト命令と7番のスピルイン命令を削除するには、第1例や第2例と同じ手順でレジスタ割付けを変更することにより、区間[3、5]から0番レジスタの割付けを外せばよい。
【0059】
この例では、
図19のステップP1~P6の順にレジスタ割付けを変更する。
【0060】
これにより、
図20に示すように、0番のスピルアウト命令と7番のスピルイン命令との間の区間[1、6]において0番レジスタの割付けが外される。よって、区間[1、6]において0番レジスタの内容が変更されなくなるため、0番のスピルアウト命令で0番レジスタのデータをメモリ3に退避させる必要がなくなる。更に、このように退避させたデータを0番レジスタに戻すための7番のスピルイン命令も不要となる。
【0061】
そこで、
図21に示すように、これらのスピルアウト命令とスピルイン命令とを削除する。これにより、前述の第1例や第2例と同様にプログラムの実行速度を向上することができる。なお、
図21では、新たに使用中となり得るレジスタに斜線のハッチングをかけてある。
【0062】
<ハードウェア構成>
次に、前述の第1例~第3例のようにレジスタ割付けを変更できるコンパイラ装置について説明する。
【0063】
図22は、本実施形態に係るコンパイラ装置のハードウェア構成図である。
【0064】
このコンパイラ装置21は、コンパイルプログラムを実行するPCやサーバ等の計算機であり、記憶部22、メモリ23、プロセッサ24、入力部25、及び表示部26を備える。これらの各部はバス27によって相互に接続される。
【0065】
このうち、記憶部22は、例えばHDD(Hard Disk Drive)やSSD(Solid State Drive)等の二次記憶装置であり、本実施形態に係るコンパイルプログラム29を記憶する。コンパイルプログラム29は、入力された命令列におけるレジスタ割付けを変更し、変更後の命令列を出力するコンパイラである。
【0066】
なお、そのコンパイルプログラム29をコンピュータが読み取り可能な記録媒体28に記録させておき、プロセッサ24に記録媒体28のコンパイルプログラム29を読み取らせるようにしてもよい。
【0067】
そのような記録媒体28としては、例えばCD-ROM(Compact Disc - Read Only Memory)、DVD(Digital Versatile Disc)、及びUSB(Universal Serial Bus)メモリ等の物理的な可搬型記録媒体がある。また、フラッシュメモリ等の半導体メモリやハードディスクドライブを記録媒体28として使用してもよい。これらの記録媒体28は、物理的な形態を持たない搬送波のような一時的な媒体ではない。
【0068】
更に、公衆回線、インターネット、及びLAN(Local Area Network)等に接続された装置にコンパイルプログラム29を記憶させておき、プロセッサ24がコンパイルプログラム29を読み出して実行するようにしてもよい。
【0069】
一方、メモリ23は、DRAM等のようにデータを一時的に記憶するハードウェアであって、その上に前述のコンパイルプログラム29が展開される。
【0070】
プロセッサ24は、自装置の各部を制御したり、メモリ23と協働してコンパイルプログラム29を実行したりするCPU(Central Processing Unit)等のハードウェアである。
【0071】
入力部25は、キーボードやマウス等の入力デバイスである。ユーザがこれらの入力デバイスを操作することにより、コンパイルプログラム29の入力先や出力先等が指定される。
【0072】
また、表示部26は、コンパイルプログラム29の実行時にユーザが使用する様々なコマンドを表示する液晶ディスプレイ等の表示デバイスである。なお、以下ではコンパイラ装置21がコンパイルプログラム29を実行する場合を例にして説明するが、ターゲットマシン1(
図1参照)がコンパイルプログラム29を実行することにより以下の各処理や機能を実現してもよい。
【0073】
<機能構成>
次に、このコンパイラ装置21の機能構成について説明する。
図23は、本実施形態に係るコンパイラ装置21の機能について示す機能構成図である。
【0074】
コンパイラ装置21は、命令列の入力を受け付けてその中の不要なスピル命令を削除する装置であって、取得部30、探索部31、変更部32、削除部33、及び追加部34を備える。これらの各部は、プロセッサ24とメモリ23が協働して前述のコンパイルプログラム29を実行することにより実現される。
【0075】
このうち、取得部30は、他のコンパイラが生成した命令列を取得する機能ユニットである。
【0076】
また、探索部31は、
図3や
図8に示したように、取得した命令列におけるレジスタ割付けを変更するために、そのレジスタ割付けの変更先の候補となるレジスタを探索する機能ユニットである。
【0077】
例えば、
図3のように1番のスピルイン命令と11番のスピルイン命令の各々に2番レジスタが割付けられており、これらの命令間の3番命令に2番レジスタが割付けられている場合を考える。この場合は、探索部31が、区間[3、3]における2番レジスタの割付けの変更先の候補を探索する。その候補は、前述のように区間[3、3]の始点で空いている11番レジスタとなる。
【0078】
また、
図8の例では、探索部31は、区間[3、6]における2番レジスタの割付けの変更先の候補を探索する。この場合の候補も、区間[3、6]の始点で空いている11番レジスタとなる。
探索部31がレジスタ割付けの変更先の候補となるレジスタを探索する際には、初めにどのレジスタの割付けを変更する目的なのかを考慮して行われる。例えば、
図12では、初めは区間[2、7]および区間[9、10]において2番レジスタを割当てないように変更することが目的である。
図12の例では、探索部31は、区間[7、7]における6番レジスタの割付けの変更先の候補を探索する。この場合の候補は、初めに区間[2、7]における2番レジスタの割付けを変更する目的であるため、2番レジスタを除いて、区間[7、7]の始点で空いている5番レジスタとする。
【0079】
一方、変更部32は、レジスタ割付けの変更を行う機能ユニットである。割付けをどのように変更するかは各レジスタが割付けられた区間を考慮して行われる。
【0080】
例えば、
図3のように、割付けの変更元の2番レジスタが区間[3、3]に割付けられており、割付けの変更先の候補の11番レジスタが区間[5、14]に割付けられている場合を考える。このように各区間[3、3]、[5、14]が重複していない場合には、区間[3、3]における割付けを2番レジスタから11番レジスタに変更する。
【0081】
一方、
図8のように、割付けの変更元の2番レジスタが区間[3、6]に割付けられており、これと重複する区間[4、14]に割付けられた11番レジスタが割付けの変更先の候補である場合を考える。この場合は、変更部32は、
図13に示したように、ステップP1~P4を実行することにより区間[4、14]における割付けを11番レジスタから10番レジスタに変更する。その後のステップP5において、変更部32は、区間[3、6]における割付けを2番レジスタから11番レジスタに変更する。
【0082】
また、削除部33は、変更部32がレジスタ割付けを変更した後に不要なスピル命令を削除する。
図6の例では、2番のスピルイン命令と11番のスピルイン命令のうち、後に実行される11番のスピルイン命令は不要となるため、削除部33は11番のスピルイン命令を削除する。また、2番と11番の間の8番のスピルイン命令も不要であるため、削除部33は8番のスピルイン命令も削除する。これについては
図15の例でも同様である。
【0083】
一方、
図20の例のように最初に0番のスピルアウト命令が実行され、その後に7番のスピルイン命令が実行される場合には、前述のようにこれらのスピル命令の両方を削除できる。そこで、この場合は、削除部33は、スピルアウト命令とスピルイン命令の両方を削除する。
【0084】
また、追加部34は、
図13~
図15に示したように、基本ブロック10の最後にコピー命令を追加する機能ユニットである。
図13の例では、2番レジスタの割付け変更先である11番レジスタが区間[4、14]に割付けられており、基本ブロック10の最後まで延びている。この場合には、プログラムの実行結果がレジスタ割付けの変更前と変わらないようにするために、追加部34は、
図15に示したように、10番レジスタの内容を11番レジスタにコピーするコピー命令を追加する。
【0085】
<フローチャート>
次に、本実施形態に係る情報処理方法について説明する。
図24は、本実施形態に係る情報処理方法について示すフローチャートである。
【0086】
まず、ステップS1において、取得部30が、他のコンパイラが生成した命令列を取得する。
【0087】
次に、ステップS2に移り、取得した命令列の中で不要なスピル命令の候補を探索部31が探索する。基本ブロック10に複数のスピル命令が存在する場合は、メモリ3内の同一のスタック番号のデータを参照しており、かつ同一のレジスタが割付けられているスピル命令が不要なスピル命令の候補となる。例えば、
図3と
図8の例では、1番、8番、11番の各スピルイン命令が不要なスピル命令の候補となる。また、
図18の例では、0番のスピルアウト命令と7番のスピルイン命令が不要なスピル命令の候補となる。
【0088】
なお、スピル命令とそれ以外の命令との弁別や、各命令に割付けられたレジスタ番号の取得等は、命令列を生成した他のコンパイラが出力するログ情報等に基づいて探索部31が行い得る。
【0089】
次に、ステップS3に移り、削除対象のスピル命令を探索部31が選択する。
【0090】
ステップS2で不要と判断されたスピル命令の全てがスピルイン命令の場合には、その中で最初に実行されるスピルイン命令を除いた後続の全てのスピルイン命令が削除対象となる。例えば、
図3と
図8の例では、8番と11番の各スピルイン命令が削除対象のスピル命令として選択される。
【0091】
また、ステップS2においてスピルイン命令と後続のスピルアウト命令とが不要と判断された場合には、これらスピルイン命令とスピルアウト命令の両方が削除対象となる。例えば、
図18の例では、0番のスピルアウト命令と7番のスピルイン命令の両方が削除対象として選択される。
【0092】
次に、ステップS4に移り、変更部32がレジスタ割付けの変更処理を行う。その変更処理の詳細については後述する。
【0093】
次に、ステップS5に移り、追加部34が、キューにコピー命令があるかどうかを判断する。キューは、
図15で説明したコピー命令をキューイングするためのデータ構造であって、追加部34がメモリ3の中に作成する。そのコピー命令は、基本ブロックの最後まで延びている区間におけるレジスタの割付けを変更した場合にキューに追加される。
【0094】
ここで、キューにコピー命令がある(YES)と判断された場合にはステップS6に移る。
【0095】
ステップS6においては、追加部34がキューの先頭のコピー命令を基本ブロックの最後に追加し、レジスタ割付けの変更前と比べてプログラムの実行結果が変わらないようにする。その後に後述のステップS7に移る。
【0096】
一方、ステップS5においてキューにコピー命令がない(NO)と判断された場合にはステップS7に移り、削除部33が不要なスピル命令を削除する。
【0097】
図3と
図8の例では、削除部33は、8番と11番の各スピルイン命令を削除する。また、
図18の例では、削除部33は、0番のスピルアウト命令と7番のスピルイン命令を削除する。
【0098】
以上により、本実施形態に係る情報処理方法の基本ステップを終了する。この後は、上記のようにスピル命令を削除した命令列を他のコンパイラに入力し、そのコンパイラがターゲットマシン1(
図1参照)で実行可能なオブジェクトファイルを生成する。
【0099】
次に、ステップS4のレジスタ割付けの変更処理について詳細に説明する。
【0100】
図25及び
図26は、本実施形態に係るレジスタ割付けの変更処理について示すフローチャートである。
【0101】
このレジスタ割付けの変更処理は、関数func(in_range, regA, rangeN, regN)を再帰的に呼び出すことで実現される。関数funcの引数のうち、in_rangeは区間を表す変数である。また、regAは、A番目のレジスタを表す変数である。そして、range Nはレジスタ割付けの変更の対象外とする区間の集合であり、regNはレジスタ割付けの変更の対象外とするレジスタである。なお、関数funcを最初に呼び出すときには、in_rangeとrangeNとを同じに設定し、regAとregNとを同じに設定する。
【0102】
なお、以下では、ステップS3における削除対象のスピル命令を除いた区間in_range内でレジスタreg Aがデータを保持する区間の集合をrange Aで表す。
【0103】
例えば、in_range = [1、10]の場合には、range A = {[1、1]、[2、5]、[7、8]}等のように表される。また、集合range Aの要素をrange Xとも書く。この例では、range X = [1、1]、range X = [2、5]、range X = [7、8]となる。
【0104】
関数func(in_range, regA, rangeN, regN)の呼び出しに先立ち、探索部31は、in_range、reg A、rangeN、regNのそれぞれの初期値をセットする。このうち、in_rangeは、ステップS1で探索した不要なスピル命令の候補のうち、最初のスピル命令から最後のスピル命令までの区間である。また、rangeN及びregNは、関数func(in_range, regA, rangeN, regN)を初めて呼び出すときに、それぞれin_range及びregAと同じ値にセットされる。例えば、
図3と
図8の例では、in_range = [1、11]、rangeN=[1、11]となる。また、
図18の例では、in_range = [0、7]、rangeN=[0、7]となる。なお、これらの区間は、
図3や
図8の命令列を生成した他のコンパイラが出力するログに基づいて探索部31が特定することができる。
【0105】
また、reg Aは、ステップS3の削除対象の各スピル命令がメモリ参照の際に使用するレジスタである。
図3と
図8の例では、メモリ3のデータの転送先である2番レジスタがreg Aとなる。そして、
図18の例では、0番のスピルアウト命令によるデータの転送元のレジスタであり、かつ7番のスピルイン命令によるデータの転送先のレジスタである0番レジスタがreg Aとなる。
【0106】
このように初期化をした後の関数funcの処理内容について説明する。
【0107】
まず、ステップS11において、探索部31が、区間in_range内でレジスタreg Aがデータを保持する区間の集合range Aを探索する。例えば、
図8の例では、in_range = [1、11]であり、reg Aは2番レジスタであり、range A = {[3、6]}となる。
【0108】
次に、ステップS12に移り、探索部31が、集合range Aの要素があるかどうかを判断する。ここで、集合range Aの要素はない(NO)と判断された場合には、区間in_range内でレジスタreg Aはデータを保持しておらず、区間in_range内でレジスタreg Aが割付けられた命令は存在しないということになる。このような状態では、
図14のように、8番のスピルイン命令を除いて区間[1、11]内で2番レジスタが割付けられた命令が存在しないため、レジスタ割付けを変更しなくても、不要な8番と11番のスピルイン命令を削除できる。
よって、この場合はレジスタ割付けを行わずに、処理に成功したものとして終了する。
【0109】
一方、ステップS12において集合range Aの要素はある(YES)と判断された場合には、区間in_range内でレジスタreg Aが割付けられた命令が存在することになる。例えば、
図8の例では前述のようにrange A = {[3、6]}となるため、集合range Aの要素はある(YES)と判断される。この場合にはレジスタ割付けの変更が必要となるため、次のステップS13に移る。
【0110】
ステップS13では、探索部31が、ステップS11で探索した集合range Aの要素である各区間のうち、始点が最も早い区間range Xを特定する。そして、その区間range Xの始点において空いているレジスタreg Bを探索する。この探索は、区間の集合rangeNにおけるレジスタregNを除いて行う。すなわち、区間rangeXの始点が区間rangeNに含まれ、かつ、レジスタregNがレジスタregBと一致するということがないようにレジスタregBを探索する。そのレジスタreg Bは、区間range Xにおけるレジスタreg Aの割付けの変更先の候補となる。
【0111】
図8の例では、range A = {[3、6]}であるから、range X = [3、6]となる。そして、range X = [3、6]の始点である3番命令で空いている11番レジスタがreg Bになる。なお、
図12の例では、rangeX=[7、7]の始点である7番命令で空いているレジスタとして2番レジスタがある。しかし、7番命令はrangeN=[1、11]に含まれ、かつregN=2であるため、2番レジスタは選ばれない。
【0112】
次に、ステップS14に移り、探索部31が、レジスタreg Bが見つかったかどうかを判断する。ここで、見つからない(NO)と判断された場合には、レジスタreg Aの割付けをレジスタreg Bに変更することができない。よって、この場合には、レジスタ割付けの変更が失敗して処理を終える。
【0113】
一方、ステップS14において見つかった(YES)と判断された場合にはステップS15に移る。
【0114】
ステップS15では、探索部31が、区間range X内でレジスタreg Bがデータを保持する区間の集合range Bを探索する。
【0115】
図8の例では、range X = [3、6]であり、かつレジスタreg Bは11番レジスタである。よって、range B = {[4、14]}となる。
【0116】
次に、ステップS16に移り、探索部31が、集合range Bの要素があるかどうかを判断する。ここで、集合range Bの要素はある(YES)と判断された場合には、このままでは区間range Xにおけるレジスタ割付けをレジスタreg Aからレジスタreg Bに変更することができない。例えば、
図8の例では、区間[3、6]におけるレジスタ割付けを2番レジスタから11番レジスタに変更することはできない。
【0117】
よって、この場合にはステップS17に移り、探索部31が、集合range Bの中で始点が最も早い区間range Yを特定する。そして、探索部31が関数func(rangeY, regB, rangeN, regN)を呼び出す再帰呼び出しを行う。
【0118】
例えば、
図8の例ではrange B = {[4、14]}であるから、range Y=[4、14]となる。
【0119】
その後、ステップS18に移り、再帰呼び出しの結果が成功したかどうかを探索部31が判断し、成功した(YES)と判断された場合にはステップS11からやり直す。また、成功しなかった(NO)と判断された場合には、レジスタ割付けの変更に失敗して処理を終える。
【0120】
一方、前述のステップS16において集合range Bの要素はない(NO)と判断された場合には、区間range_X内でレジスタreg Bが割付けられた命令は存在しないということになる。例えば、
図12の例では、range_X=[7、7]であり、regBは5番レジスタとなっているため、range B={}となり、区間[7、7]内で5番レジスタが割付けられた命令は存在しない。
【0121】
よって、この場合にはステップS19に移り、変更部32が、区間range_Xにおけるレジスタ割付けをレジスタreg Aからレジスタreg Bに変更する。例えば、
図13の例でrange_X=[7、7]であり、reg Aが6番レジスタであり、reg Bが5番レジスタである場合には、区間[7、7]におけるレジスタ割付けを6番レジスタから5番レジスタに変更する。
【0122】
次に、ステップS20に移り、追加部34が、区間range_Xが基本ブロックの最後まで延びているかどうかを判断する。例えば、
図13の例でrange_X=[4、14]の場合には、区間range_Xが基本ブロックの最後まで延びていると判断される。
【0123】
このように延びている(YES)と判断された場合には、ステップS21に移り、追加部34が、レジスタreg Bの内容をレジスタreg Aにコピーするコピー命令をメモリ3内のキューに追加する。例えば、前述の
図13の例でrange_X=[4、14]であり、reg Aが11番レジスタであり、reg Bが10番レジスタである場合には、10番レジスタの内容を11番レジスタにコピーするコピー命令をキューに追加する。
【0124】
なお、ステップS20において延びていない(NO)と判断された場合にはキューにコピー命令を追加することなく処理を終える。
以上により、本実施形態に係るレジスタ割付けの変更処理の基本ステップを終了する。
【0125】
上記した本実施形態によれば、
図24のステップS4でレジスタ割付けの変更処理を行うことで、各スピル命令の間の区間でレジスタの空きを作ることができ、ステップS7で不要なスピル命令を削除することができる。これにより、プログラムに含まれる命令数を低減できると共に、プログラム実行時のメモリアクセスの回数が減るため、プログラムの実行速度を向上させることができる。
【0126】
以上、本実施形態について詳細に説明したが、本実施形態は上記に限定されない。例えば、
図25及び
図26では関数funcの再帰呼び出しによりレジスタ割付けの変更処理を行ったが、関数の再帰呼び出しを行わずに、ループ処理によりレジスタ割付けの変更処理を行ってもよい。
【符号の説明】
【0127】
1…ターゲットマシン、2…プロセッサ、3…メモリ、4…演算部、5…レジスタファイル、21…コンパイラ装置、22…記憶部、23…メモリ、24…プロセッサ、25…入力部、26…表示部、27…バス、28…記録媒体、30…取得部、31…探索部、32…変更部、33…削除部、34…追加部。