是什么让值不安全地存储在寄存器中?

What makes a value unsafe to be stored in a register?

在谈论寄存器分配时,有关编译的文章(例如 Cooper 的 Engineering a Compiler)经常提到存储在寄存器中的值需要 "safe" - 否则它们应该存储在内存中。

是什么让值不安全地保存在寄存器中?

编辑:书中的上下文:

"In a memory-to-memory model, the allocator must determine which values can be kept safely in registers—that is, which values are unambiguous."

我能找到的最有用的信息是 "Register promotion uses data-flow analysis of pointer values to determine when a pointer-based value can safely be kept in a register throughout a loop nest and to rewrite the code so that the value is kept in a newly introduced temporary variable."

所以要澄清这个问题:为什么指针值存储在寄存器中是不安全的,并且这是值不能安全存储在寄存器中的唯一情况吗?

我的理解是,这主要是 aliases 的问题。别名是在程序中的某个时刻引用同一对象的两个或多个名称。

别名使得执行一些重要的优化变得非常困难。考虑以下 C 示例:

int first, second, *p, *q;
...
first = *p; // store the value from the variable referred to by p in first
*q = 3;     // assign to the variable referred to by q
second = *p;     // store the value from the variable referred to by p in second

在大多数机器上,对 first 的初始分配将要求将 *p 加载到寄存器中。由于访问内存的开销很大,编译器会希望保留加载的值,并在对 second 的赋值中重用它。但是,它将无法这样做,除非它可以验证 pq 不引用同一个对象(即 *p*q 不是别名) .

为验证某些名称不是别名而进行的分析称为 alias analysis,并确定何时可以将值安全地缓存在寄存器中、计算 "out of order" 或由并发线程访问。

代码略有不同:

static int x;
int* p;
int first, second;

first = x;
*p = 3;
second = x;

对 *p 的赋值可能已经改变了 x,因此赋值 second = x 必须再次从内存中读取 x 并且不能使用刚刚存储在 first 中并且可能仍在寄存器中的值。

当您使用指针变量时,寄存器存储的可用性并不能保证程序的执行速度更快。例如,如果声明了太多的寄存器变量,或者没有足够的寄存器来存储所有这些变量,则必须将某些寄存器中的值移动到内存中的临时存储区,以便为其他变量清除这些寄存器。而且在这个过程中,将寄存器内存移动到临时内存变得不安全。

因此,在寄存器和内存位置之间来回移动数据可能会浪费很多时间。此外,将指针变量用于变量存储可能会干扰编译器对寄存器的其他使用,例如在表达式计算中存储临时值。最后,正如我提到的,在这种特殊情况下,使用寄存器变量实际上可能会导致执行速度变慢。仅当您对所用计算机的体系结构和编译器有详细了解时才应使用寄存器变量。

如果您使用要放入寄存器的指针变量,最好查看相应的手册。