命令レジスタファイル

教授から渡された論文を読む。組込みプロセッサのアーキテクチャについてのもので、それほど興味はなかったのだが、ゼミでそれについて発表しろとのことなので読まなくてはいけなかったのだ。
テーマは命令レジスタファイル(IRF)というものを使ってコードサイズ、消費電力、実行時間を減らすというもの。普通はこれら3つをすべて減らすのは難しい。コードサイズを減らすと実行時間は増えるもんだ。しかし、このペーパではIRFとそれに付随する即値テーブル(IMM)を利用することによりそれが可能になると言っている。なかなか興味深い。
では、IRFとはどんなものなのか。まあ、簡単に言うと普通のレジスタファイルと同じようなものである。レジスタファイルはデータを保存するが、IRFは命令を格納する。論文では32個のレジスタからなるとしている。要はこのレジスタに良く出てくる命令を入れておくことによって、命令メモリ(キャッシュやROM)へのアクセスを減らそうとういものだ。メモリへのアクセスが少なくなればその分消費電力が減るのでこれは良いことです。
IRFの命令へのアクセスは、メモリに格納される通常の命令のなかの一部分を用いて行う。論文ではMIPSのRタイプ命令のShamt部分*1のところをIRFへのポインタとしている。例えば、

0: add r3, r1, r2
1: add r4, r3, r3

という命令列があったとして、命令1がIRFの15番目に格納されているとすると、この命令列のコードは、

+----+----+----+----+-----+-----+
|0(6)|1(5)|2(5)|3(5)|15(5)|32(6)|
+----+----+----+----+-----+-----+

となる。本来は2命令なのにメモリに格納されるコードは1命令分のみとなり、コードサイズを減らすことが可能となる。ただし、この場合はIRFに命令をロードする命令が必要になるので実際には2命令分のコードが必要である。実際にIRFに格納される命令は良く使われる命令なので命令ロード分を考えてもコードサイズは小さくなるはずである。ちなみにこの論文では、このようなMIPSのRタイプをちょこっと変えただけのものだけじゃなく、Tタイプという新しいフォーマットを作りより多くの命令を1つの命令(32ビット)にパックしている。つまり、オプコード部(MIPS命令フォーマットの上位6ビット部分)以外の26ビットを5つのフィールドに分け、最大で5つのIRFに格納されている命令を指定することができる*2。これを使えば理想的な場合ならコードサイズを5分の1にできるわけだ。もちろんそう上手く行くわけはないだろう。ちなみに、指定する命令がない場合はNOP(IRFの0番目に格納されている)を入れてTタイプの命令を構成する。この辺はVLIWと似ている。
しかし、このようなアーキテクチャだとハードウェアよりもコンパイラアセンブラが問題になる。IRFは命令セットから見えるので(というか命令セットを変更している)、既存のコンパイラでは動かせないし、効率がよいコードを得るにはそれなりのコンパイラが必要である。まず考えなくてはいけないのはどの命令をIRFに格納するかである。これはプロファイリングを使ってよく使われる命令を調べることによって決めているようだ。なお、IRFに格納する命令をより一般化するために即値テーブルとPositionalレジスタ(日本語訳がわからない)というものがアーキテクチャに盛り込まれている。早い話が、即値部分だけ違うIタイプの命令はおなじIRFに格納できるとういふうになっている。

addi r1, r2, 100
addi r1, r2, 200

この二つの命令はおなじIRFに格納され、即値の100と200が即値テーブルに保存される。即値テーブルから値を読み出すためには、それ用のTタイプ命令を使う必要がある。そのようなTタイプ命令の場合は5ビットのフィールドを即値テーブル参照用に使うためパックできる命令数が5つよりも少なくなる。Positionalレジスタも同様で、これはレジスタ参照をそのレジスタが使われる二つの命令の相対位置で表現することにより、命令を抽象化し、おなじIRFに格納できる命令を増やしている。

a0: add r2, r1, r0
a1: add r3, r2, r2

b0: add r4, r2, r8
b1: add r3, r4, r4

という命令列の場合、a1とb1はIRFの命令に置いてはおなじとみなされる(と思う。ちょっとこの辺怪しいな)。
これだけアーキテクチャに変更を加えるとなるとそれなりの結果がないと実際にチップとしては出てこないと思う。この論文によると、コードサイズは80%から90%、命令フェッチ部の消費電力は60%から70%、と結構良さそうなシミュレーション結果が出ている。しかし、実行時間はほとんど変わらない。ただし、面白いことにセキュリティ系のベンチマークプログラムでは実行時間が70%となっている。
このアーキテクチャはなかなか面白いし、結果を見る限りそれなりに優秀っぽいが、ちょっと複雑すぎる気がする。IRFもIMMも命令セットから見えるため、コンテキストスイッチ時にはそれらを保存しなければならない。IRFとIMMをすべてのプログラムで同一のものにすればそんなことする必要はないが、そうするとIRFの恩恵が減る。また、例外時の処理が難しい。パックされた命令を実行している時に例外が発生した場合、どうするか。パックされた命令の何番目で例外が発生したかを記録する機構を用意するか、例外が発生した場合はパックされた命令の最初から実行するように例外が発生したらその前にある一緒にパックされた命令をキャンセルするようにすればよいだろう。ちなみにこのコンテキストスイッチと例外という問題点はペーパに書いてあることです・・・
しかし、このようなアーキテクチャを見て、拡張として誰もが思いつくのはレジスタウィンドウですね。私も読みながらレジスタウィンドウをつけたらどうなるだろうと思った。まあ、私が思いつくくらいですからね、もちろん論文のFuture Workにそんなことが書いてありましたよ。
それにしても、やはりプロセッサアーキテクチャは面白いな。最近、プログラミング言語についてばかり勉強してたから、余計にそう感じるのかな。

*1:シフト命令のシフト量指定に使われる部分。5ビット。シフト命令以外の時は使われない。MIPS命令セットで気に食わない部分トップ3に入るところ。

*2:5ビットのフィールドが5つ。残りの1ビットはそのフィールドの使い方を決めるのに使われるのだが、詳しくは論文を読んでね