[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

17.6 レジスタクラス

多くのマシンでは、番号のついたレジスタが全て等価であるとは限らない。 例えば、あるレジスタ群はインデックスアドレッシングには使用できないとか、 あるレジスタ群は一部の命令では使用できない等々。 このようなマシンによる制限は、レジスタクラス を使って、 コンパイラに知らせる。

レジスタクラスはたくさん定義することができ、それぞれに名前を与えて、 どのレジスタがそのクラスに所属するかを指定する。 そうしておけば、オペランドとして許されるレジスタクラスを特定の 命令パターンに対して指定することができる。

一般に、各レジスタは色々なクラスに所属することになる。 事実、ALL_REGS というクラスを作り、全てのレジスタを所属させなくては ならない。もう一つ別の、NO_REGS というクラスを作らなくてはならず、 このクラスに所属するレジスタはない。 二つのクラスの和を作ると別のクラスになることもあるが、 必須ではない。

必須のクラスの一つに GENERAL_REGS がある。 この名前には何も特別な意味はないが、オペランドの制約文字 ‘r’ と ‘g’ はこのクラスを指す。 GENERAL_REGSALL_REGS が同じなら、単に ALL_REGS に展開されるマクロとして定義する。

クラスを順序付けて、クラス x がクラス y に 含まれるなら、x のクラス番号は y の番号より小さくなるように する。

GENERAL_REGS 以外のクラスのオペランド制約での指定方法は、 機種依存のオペランド制約文字によって行なわれる。 色々なクラスに対応する制約文字を定義し、オペランド制約でそれを 使うことができる。

ある命令が二つのクラスを両方とも許すような場合は常に、その二つのクラスの 和となるクラスを定義すべきである。 例えば、ある命令のある特定のオペランドとして、浮動小数点(コプロセッサ) レジスタと汎用レジスタのどちらでも使えるなら、その両方を含む、 FLOAT_OR_GENERAL_REGS というクラスを定義すべきである。 そうしないと生成されるコードが最上のものではなくなる。

また、そのレジスタクラスについて、ある種の冗長な情報を指定しなければ ならない。 クラス毎に、そのクラスを含んでいるクラスと、そのクラスに 含まれるクラスを指定し、クラスの対毎に、その対の和に含まれる最大のクラスを 指定する。

複数の連続するレジスタを占める値がある特定のクラスに入ることが 期待されるときは、それに使われるレジスタが全てそのクラスに所属 しなければならない。 このため、レジスタクラスを使って、レジスタ対を偶数番レジスタで始まるように 強制的に要求することは出来ない。そのためには、HARD_REGNO_MODE_OK を 使う。

ビット毎の論理積やシフト命令の入力オペランドに使われるレジスタクラスには 特別な要件がある。そのようなクラスはそれぞれ、 固定小数点マシンモード毎に、そのモードからメモリへ、あるいはメモリから そのモードへ転送可能なレジスタのサブクラスがなければならない。 例えば、機種によっては、一バイト値(QImode)についての 演算は特定のレジスタに限られる。 その場合、ビット毎の論理積やシフト命令で使われる各レジスタクラスは、 それから一バイト値をロードしたりストア可能なレジスタからなるサブクラス がなければならない。 これは、PREFERRED_RELOAD_CLASS が常に可能な値を返すことができる ようにするためである。

enum reg_class

ある列挙型で、全てのレジスタクラス名を列挙値として定義しなければならない。 NO_REGS は先頭に来なければならない。 ALL_REGS は最後のレジスタクラスとならなくてはならず、 その後にさらに一個の列挙値 LIM_REG_CLASSES が続く。 LIB_REG_CLASSES は、レジスタクラスではないが、クラスが幾つあるかを 知らせるためにある。

各レジスタクラスは番号を持っており、それは クラス名を int 型に キャストした値である。この番号は、以下に説明する多くの表の添え字として 使われる。

N_REG_CLASSES

区別できるレジスタクラスの数であり、以下のように定義される。

 
#define N_REG_CLASSES (int) LIM_REG_CLASSES
REG_CLASS_NAMES

レジスタクラス名を C の文字列定数として持つ初期化子。 この名前は、デバッグ出力で使われることがある。

REG_CLASS_CONTENTS

レジスタクラスの内容をビットマスクである整数として含む初期化子。 n 番目の整数は、クラス n の内容を指定する。 整数 mask は次のように解釈される。 もし、mask & (1 << r) が 1 なら、レジスタ r は そのクラスに所属する。

レジスタが 32 より多い機種では、このためには一個の整数では足りない。 その時は、整数は副初期化子で置き換えられる。副初期化子は、複数の整数を 中括弧で囲んだものである。 各副初期化子は、‘hard-reg-set.h’ で定義されている HARD_REG_SET 型の初期化子として適切でなければならない。

REGNO_REG_CLASS (regno)

ハードレジスタ regno を含むレジスタクラスを表す値を持つ C の式。 一般にはそのようなクラスは複数ある。その場合、「最小」のクラス、 つまり、そのレジスタを含むそれ以上小さなクラスがないようなクラスを選ぶ。

BASE_REG_CLASS

ベースレジスタとして有効なレジスタが所属しなければならないクラス名を 定義するマクロである。 ベースレジスタとは、レジスタの値に変位を加算したものをアドレスとするときに 使われるレジスタである。

INDEX_REG_CLASS

インデックスレジスタとして有効なレジスタが所属しなければならないクラス名を 定義するマクロである。 インデックスレジスタとは、その値をスケール因子分掛けたものか、 別のレジスタに加算した(同様に変位にも加算される)ものをアドレスとするときに 使われるレジスタである。

REG_CLASS_FROM_LETTER (char)

レジスタクラスについての機種依存のオペランド制約文字を定義する C の式。char があるオペランド制約文字なら、 この値は対応するレジスタクラスとなる。 オペランド制約文字以外なら、この値は NO_REGS とする。 GENERAL_REGS クラスに対応するレジスタ文字 ‘r’ は、 このマクロには渡されないであろうから、それを扱う必要はない。

REGNO_OK_FOR_BASE_P (num)

レジスタ番号 num がオペランドのアドレスのベースレジスタとして 使うのに適当なものなら、0 でない値を持つ C の式。 適切なハードレジスタか、あるいは適切なハードレジスタが割り当て済の 疑似レジスタのどちらでも良い。

REGNO_MODE_OK_FOR_BASE_P (num, mode)

REGNO_OK_FOR_BASE_P と同様の C の式だが、 この式は mode のメモリ参照のモードを調べる。 メモリ参照のモードが、あるレジスタをベースレジスタとして使って良いか どうかに影響するなら、このマクロを定義する。 このマクロが定義してあると、コンパイラは REGNO_OK_FOR_BASE_P の 代わりにこちらを使う。

REGNO_OK_FOR_INDEX_P (num)

レジスタ番号 num がオペランドのアドレスのインデックスレジスタとして 使うのに適当なものなら、0 でない値を持つ C の式。 適切なハードレジスタか、あるいは適切なハードレジスタが割り当て済の 疑似レジスタのどちらでも良い。

インデックスレジスタとベースレジスタの違いは、インデックスレジスタは スケーリングされることである。 あるアドレスが二つのレジスタの和を含んでいて、そのどちらもスケーリング されないのであれば、どちらか一つが「ベース」となり、他方は「インデックス」 というラベルが貼られる。だが、どちらのラベル付が使われても、レジスタが それぞれの役割を果たす、その機種の制約に収まらなければならない。 コンパイラは両方のラベル付を試して、有効なものを一つ見つけ出し、 どちらのラベル付も動作しない場合にのみ、一方のレジスタ、あるいは両方の レジスタを再ロードする。

PREFERRED_RELOAD_CLASS (x, class)

x をクラス class のレジスタにコピーする必要があるときに 使うレジスタクラスについて制限を追加する C の式。 この式の値はあるレジスタクラスである。おそらく class か、 別のより小さなクラスである。多くの機種では、以下の定義が安全である。

 
#define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS

より制限の強いクラスを返したほうが良いコードが出るということが 時々ある。 例えば、68000 の場合には、x が ‘moveq’ 命令で有効な範囲内に ある整数定数であるときは、このマクロの値は class がデータレジスタを 含んでいる限り、常に DATA_REGS になる。

xconst_dobule の場合、NO_REGS を 返すことにより x を強制的にメモリ定数とすることができる。 これは、浮動小数点即値をある種のレジスタにはロード出来ないようなマシンで 役に立つ。

PREFERRED_OUTPUT_RELOAD_CLASS (x, class)

PREFERRED_RELOAD_CLASS と同様だが、入力の再ロードではなく 出力の再ロード向けである。 このマクロを定義しない場合は、デフォルトは class がそのまま 使われる。

LIMIT_RELOAD_CLASS (mode, class)

一個の C の式。モード mode の値を、通常 クラス class が使われる 再ロード・レジスタで保持することが可能であることが必要な場合に 使うレジスタクラスについて制限を追加する。

PREFERRED_RELOAD_CLASS とは違って、このマクロは 単純にはある再ロードクラスに入らない、ある種のモードが存在するときに 使われるべきである。

この値はレジスタクラスである。おそらく、class か何か別の より小さなクラスであろう。

このマクロは、ターゲット機種の制限により、このマクロで何か自明では ないことをする必要があるとき以外は定義しないこと。

SECONDARY_RELOAD_CLASS (class, mode, x)
SECONDARY_INPUT_RELOAD_CLASS (class, mode, x)
SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, x)

多くの機種では、直接メモリへ、あるいはメモリからコピーできないレジスタが ある。あるいは、他の型のレジスタからのコピーさえもできないレジスタが 存在することもある。 例えば、‘MQ’ レジスタは、多くの機種で、汎用レジスタとの間でしか コピー出来ず、メモリとの間でのコピーはできない。 機種によっては全てのレジスタとメモリ間でのコピーを許しているものがあるが、 あるメモリ位置(例えば、RT のシンボリック・アドレスや、PIC をコンパイルする 時の SPARC の特定のシンボリック・アドレス等)を格納するには スクラッチレジスタを必要とするものがある。 場合によっては、中間レジスタとスクラッチレジスタの両方が必要である。

このマクロを定義して、再ロード・パスに、 再ロードのためには、データを保持するレジスタに加えて、少なくとも一個の レジスタを割り当てる必要があることを知らせるようにすべきである。 特に、xmode のレジスタ class にコピーするのに 中間レジスタが必要な場合は、SECONDARY_INPUT_RELOAD_CLASS を 定義して、それに属する全てのレジスタが中間レジスタやスクラッチレジスタ として使えるような最大のレジスタを返すようにすべきである。

mode のレジスタ classx にコピーするのに 中間レジスタやスクラッチレジスタが必要な場合は、 SECONDARY_OUTPUT_RELOAD_CLASS を 定義して、必要とされる最大のレジスタを返すようにすべきである。 入力再ロードと出力再ロードの要件が同じなら、これらの二つのマクロを 同じ定義にする代わりに、マクロ SECONDARY_RELOAD_CLASS を 使うべきである。

これらのマクロが返す値はしばしば GENERAL_REGS となる。 予備のレジスタが必要でない場合は NO_REGS を返す。 これは、x と モード mode でクラス class のレジスタの 間で、スクラッチレジスタなしで直接コピー可能な場合である。 常に NO_REGS を返すのならこのマクロは定義しないこと。

スクラッチレジスタが必要な場合(中間レジスタの必要の有無に関わらず)、 see section RTL生成用標準パターン名 で必要とされる、‘reload_inm’ か ‘reload_outm’ のパターンを定義すべきである。 これらのパターンは、通常 define_expand で実装され、 オペランド 2 がスクラッチレジスタである点を除いて、‘movm’ の パターンと同じにすべきである。

一個のレジスタクラスを含む再ロードレジスタとスクラッチレジスタに 対する制約を定義する。元の再ロードレジスタ(クラスが class)が パターンで指定された制約に当てはまるなら、このマクロが返す値が スクラッチレジスタのクラスとして使われる。 当てはまらないのであれば、再ロードレジスタが二つ追加で必要になる。 その二つのレジスタのクラスは、insn パターンの制約から得られる。

x は、疑似レジスタか疑似レジスタの subreg でなければ ならない。これらは、ハードレジスタかメモリのどちらかにある。 どちらにあるかは、true_regnum を使って調べる。 疑似レジスタがメモリにあれば -1 を返し、レジスタにあればハードレジスタ 番号を返す。

このマクロは、ある特定のクラスのレジスタはメモリにだけコピー可能であり、 もう一つの別のクラスのレジスタにはコピーできないという場合は 使うべきでない。その場合、二番目の再ロードレジスタは不要であり 役に立たない。代わりに、スタック位置を使ってコピーを行なわなければならず、 movm パターンはメモリを中間の格納場所として使うべきである。 これは、浮動小数点レジスタと汎用レジスタの間で良く起こることである。

SECONDARY_MEMORY_NEEDED (class1, class2, m)

特定の機種には、レジスタの幾つかはメモリを使わないと他のレジスタに コピーできないという性質がある。そういう機種では、このマクロを次の ような一個の C の式に定義する。すなわち、この式は、 class1 のレジスタにあるモード m のオブジェクトがクラス class2 のレジスタにコピーできるのは、class1 のレジスタを メモリにストアしてそのメモリ位置を class2 のレジスタにロードする 場合だけなら、ゼロでない値となる。

このマクロは、値が常にゼロになるようなら定義しないこと。

SECONDARY_MEMORY_NEEDED_RTX (mode)

SECONDARY_MEMORY_NEEDED が定義されていると普通、コンパイラが レジスタのコピーに必要なメモリ位置用のスタックスロットを割り当てる。 このマクロが定義されていると、コンパイラは代わりに、このマクロで 定義されるメモリ位置を使う。

SECONDARY_MEMORY_NEEDED を定義しない場合は、このマクロを 定義しないこと。

SECONDARY_MEMORY_NEEDED_MODE (mode)

コンパイラが、モード mode の二つのレジスタ間でコピーするのに 第二のメモリ位置を必要とするときは、普通は、BITS_PER_WORD ビットの量を 保持するのに充分なメモリを確保し、ストアとロード操作を、多ビット幅で そのクラスが mode のクラスと同じであるモードで実行する。

これはほとんどの機種でなすべき正しいことである。レジスタの全ビットが コピーされ、レジスタを狭いモードでアクセスするのを抑止しているからである。 これにより、機種によっては浮動小数点レジスタを禁止する。

だが、このデフォルトの動作が正しくない機種もある。例えば、DEC Alpha が そうで、short 型の整数を浮動小数点レジスタにストアする仕方と 整数レジスタにストアする仕方が異なる。こういう機種では、デフォルトの 拡幅が正しく動作しないので、このマクロを定義して、ある場合には拡幅を 抑制しなければならない。詳細については ‘alpha.h’ を参照のこと。

SECONDARY_MEMORY_NEEDED を定義しない場合や、modeBITS_PER_WORD ビット長のモードに広げるのが正しい機種の場合は、 このマクロを定義しないこと。

SMALL_REGISTER_CLASSES

機種によっては、ハードレジスタを任意の insn 群を越えて生存させるのは 危険が伴う場合がある。こういう機種は普通、特定のレジスタ(例えば アキュムレータ)に値が入っていないといけない命令を持っているので、 必要とされるハードレジスタがこのような insn を越えて、別の目的に 使われると、再ロードに失敗する。

そういう機種では、SMALL_REGISER_CLASSES をゼロでない値を持つ 式として定義する。このマクロの値がゼロでないと、コンパイラは ハードレジスタの生存期間を最小化することを試みる。

このマクロをゼロでない値に定義するのは常に安全である。だが、 不必要に定義すると、ある場合に実行可能な最適化の程度が減ることになる。 必要な場合にこのマクロをゼロでない値に定義しないと、コンパイラは スピルレジスタを使いつくし、致命的エラーのメッセージを出力する。 ほとんどの機種では、このマクロは何も定義すべきでない。

CLASS_LIKELY_SPILLED_P (class)

一個の C の式。この式の値は、クラス class のレジスタに割り当てられた 疑似レジスタが、class のレジスタはスピルレジスタとして必要 であるために、スピルされそうならゼロでない値となる。

このマクロのデフォルト値は、class にレジスタがちょうど一個ある 場合は 1 を返し、それ以外の場合はゼロを返す。 ほとんどの機種では、このデフォルトを使うべきである。 このマクロを何か他の式に定義するのは、‘local-alloc.c’ で割り当てられた 疑似レジスタが、それ用のハードレジスタがスピルレジスタ用に必要であるために、 結局メモリに取られる場合だけにすること。 このマクロが指定されたクラスに対してゼロでない値を返すなら、そのクラスの 疑似レジスタは ‘global.c’ でだけ割り当てられる。‘global.c’ は、 疑似レジスタを別のレジスタに再割当する方法を知っている。 再割当に使える別のレジスタがない場合は、このマクロの定義を変えるべきでない。 なぜなら、そういう場合は、定義を変えるとレジスタの割当を遅くするだけで あるから。

CLASS_MAX_NREGS (class, mode)

C の式。モードが mode の値を保持するのに必要な、クラス class の連続するレジスタの最大数を表す。

これは、マクロ HARD_REGNO_NREGS と密接に関係する。 実際、マクロ CLASS_MAX_NREGS (class, mode) の 値は、クラス class の全ての regno の値について、 HARD_REGNO_NREGS (regno, mode) の最大値と なるべきである。

このマクロは、再ロードパスにおいて複数ワードの値の扱いを制御する 手助けをする。

CLASS_CANNOT_CHANGE_SIZE

一個の C の式。定義されていれば、 レジスタにロードしたときのモードと同じサイズのモードでコンパイラが常に アクセスしなければならないレジスタを含むクラスを表す。

例えば、Alpha の場合は、32ビットの整数オブジェクトか浮動小数点オブジェクトを 浮動小数点レジスタにロードすると、64ビットに拡張される。 したがって、64ビットのオブジェクトをロードし、次に 32 ビットのオブジェクト としてストアすると、普通のレジスタがそうであるように、 下位の 32 ビットはストアされない。 このため、‘alpha.h’ ではこのマクロを FLOAT_REGS として 定義している。

他に特別なマクロが三つあって、どのオペランドがどの制約文字に収まるかを 記述する。

CONST_OK_FOR_LETTER_P (value, c)

一個の C の式。この式は、特定の範囲の整数値を指定する、 機種依存のオペランド制約文字(‘I’、‘J’、‘K’、… ‘P’) を定義する。c がこれらの文字のどれかであれば、この式で、ある 整数である value が適切な範囲にあるかどうかを調べ、そうであれば 1 を返し、それ以外の場合は 0 を返す。c がこれらの文字でなければ、 value の値によらずにこの式の値は 0 とすべきである。

CONST_DOUBLE_OK_FOR_LETTER_P (value, c)

一個の C の式。この式は、特定の範囲の const_double の値を 指定する機種依存のオペランド制約文字を定義する(‘G’ か ‘H’)。

c がこれらの文字のどれかであれば、この式で、コード const_double の RTX である value を調べて、適切な範囲にあれば 1 を返し、 それ以外の場合は 0 を返す。c がこれらの文字でなければ、value に関わらず、この式の値は 0 とすべきである。

const_double は、全ての浮動小数点定数と DImode の 固定小数点定数に使われる。与えられた文字は、どちか片方の値、 あるいは両方の値を受け入れることができる。GET_MODE を 使ってこの二つの種類を区別することができる。

EXTRA_CONSTRAINT (value, c)

一個の C の式。オプションの機種依存制約文字(‘Q’、‘R’、‘S’、 ‘T’、‘U’)を定義する。これらの式を使って、ターゲット機種の 特定の型のオペランド、普通はメモリ参照を区別することができる。 普通は、このマクロは定義されない。ある特定のターゲット機種で必要な 場合は、value が、制約文字 c で表現されるオペランドの型に 対応するなら 1 を返す必要がある。c が追加の制約として 定義されていない場合は、返される値は value に関わらずに 0 に ならなければならない。

例えば、ROMP では、ロード命令は、メモリ参照がシンボリックアドレスを 含んでいれば、出力を r0 に置くことができない。 制約文字 ‘Q’ が、シンボリックアドレスを含まないメモリアドレスを 表現するものとして定義されている。ある選択肢が、入力に制約 ‘Q’ が、 出力に ‘r’ が指定されている。次の選択肢は、入力に ‘m’ が、 出力には r0 を含まないレジスタクラスが指定されている。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated using texi2html 1.78.