在编译器设计中,为什么调用者无法将其使用的寄存器列表(在调用者保存安排的情况下将其推送)传递给被调用者而不是具有调用者或被调用者寄存器保存安排,以便被调用者可以将其使用的寄存器列表与调用者使用的寄存器进行比较。然后只推送真正需要推送的寄存器。我错过了什么吗?
答案 0 :(得分:5)
这是一个有趣的想法。我认为有两件事情使它不那么有吸引力:
以下是对它如何工作的一点阐述: 您希望调用者将列表打包为机器字作为位向量。然后,您将需要被调用者按位 - 并使用自己的列表,有一条指令保存由结果位向量命名的所有寄存器。
因为在最坏的情况下你将不得不在堆栈上保留空间,所以你不需要节省太多 - 在一个现代的,超标量的,无序的处理器上,写入相同的高速缓存行几乎是免费。
如果您真正想要的是在运行时最小化加载和存储的数量,那么您也可以使用所有调用者保存寄存器。这种策略也使得引发异常和先发制人地切换线程变得非常便宜,而且很多编译器(如OCaml)也因此使用它。 Callee-saves寄存器是一种试图减少溢出和重载指令的代码大小的黑客行为。它们在许多情况下都可以工作,并且它们节省了空间,因为调用站点远远超过了过程定义(平均而言,一个过程包含多个调用)。
有关调用者保存和被调用者保存寄存器之间权衡的更多信息,有一个nice paper by Jack Davidson and David Whalley。
答案 1 :(得分:2)
效率非常低......你需要解析列表(对于每个函数!),这是完全没必要的。