Compiler construction 是什么使得存储在寄存器中的值不安全?

Compiler construction 是什么使得存储在寄存器中的值不安全?,compiler-construction,register-allocation,Compiler Construction,Register Allocation,在谈到寄存器分配时,有关编译的文本(例如,库珀的《设计编译器》)经常提到寄存器中存储的值必须是“安全的”——否则它们应该存储在内存中 是什么使值保存在寄存器中不安全 编辑:书中的上下文: 在内存到内存模型中,分配器必须确定哪些值可以安全地保存在寄存器中,也就是说,哪些值是明确的 我能找到的最有用的一点是 “寄存器升级使用指针值的数据流分析来确定基于指针的值何时可以在整个循环嵌套中安全地保存在寄存器中,并重写代码,以便将该值保存在新引入的临时变量中。” 为了澄清这个问题:为什么指针值存储在寄存器中

在谈到寄存器分配时,有关编译的文本(例如,库珀的《设计编译器》)经常提到寄存器中存储的值必须是“安全的”——否则它们应该存储在内存中

是什么使值保存在寄存器中不安全

编辑:书中的上下文:

在内存到内存模型中,分配器必须确定哪些值可以安全地保存在寄存器中,也就是说,哪些值是明确的

我能找到的最有用的一点是 “寄存器升级使用指针值的数据流分析来确定基于指针的值何时可以在整个循环嵌套中安全地保存在寄存器中,并重写代码,以便将该值保存在新引入的临时变量中。”


为了澄清这个问题:为什么指针值存储在寄存器中是不安全的,而这是唯一一个值存储在寄存器中不安全的情况吗?

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

别名使得执行一些重要的优化非常困难。考虑下面的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
时重用它。但是,它将无法这样做,除非它可以验证
p
q
不引用同一对象(即
*p
*q
不是别名)


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

稍有不同的代码位:

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

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

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

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

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


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

在上下文中使用“安全”和/或在书的索引中查找“安全”将有助于提供Cooper的引用。谢谢,我现在编辑了这个问题。我不确定第一个引用,但第二个是关于别名分析——编译器可以证明通过指针加载的值在整个循环中不会改变,因此不需要在每次迭代中加载。