まず、C 標準では、宣言された変数のアドレスを取得することを禁止しています。これは、s のregister
ビット フィールドの場合と同様ですstruct
。
非登録 (「自動」) 変数の場合、短い答えは「はい」です。オプティマイザの最も単純な戦略は、アドレスが取得された変数をすぐにスピルすることです。
「スピル」は、レジスタ割り当ての文献からの用語であり、「レジスタではなくメモリに配置することを決定する」ことを意味します。
洗練されたオプティマイザーは、アドレスが取得されたとしても、エイリアス分析を実行し、レジスターに値を保持することができます。これは、結果のポインターを使用して値を変更できない可能性があることが証明できる場合はいつでも可能です。
関連するもう 1 つの最適化は、ライブ範囲分割です。これにより、変数が有用な値を保持している命令範囲の一部 (「ライブ範囲」) のレジスタに変数を格納し、他の部分にスピルすることができます。この場合、こぼれた部分は、ポインターを使用して変数の値を変更できる場所に対応します。例えば:
x = 3;
... lots of computations involving x
if T {
// SPILL HERE, so store register holding x to memory
int *p = &x;
... lots of computations, perhaps using p to change x
*p = 2;
// DONE SPILL HERE, so reload register
... more code here not using p to change x.
}
else {
... lots of computations involving x.
}
このコードの積極的なオプティマイザーは、x のスタック位置を割り当てる可能性がありますが、それをコードの上部にあるレジスターにロードし、SPILL としてマークされた領域を除いてそこに維持します。この領域は、メモリへのレジスタのストアと一致するレジスタのロードによって囲まれます。