Compiler construction 被调用方是否在调用方传递已用寄存器的情况下保存?

Compiler construction 被调用方是否在调用方传递已用寄存器的情况下保存?,compiler-construction,cpu-registers,register-allocation,Compiler Construction,Cpu Registers,Register Allocation,在编译器设计中,为什么调用方不能将其已用寄存器列表(在调用方保存协议的情况下会推送)传递给被调用方,而不是使用调用方或被调用方寄存器保存协议,以便被调用方可以将其已用寄存器列表与调用方使用的寄存器进行比较。然后,只有真正需要推送的寄存器才会被推送。我遗漏了什么吗?效率很低。。。您将需要解析列表(对于每个函数!),这是完全不必要的。这是一个有趣的想法。我认为有两件事使它不那么吸引人: 无论如何,被调用方必须为最坏的情况保留堆栈空间 为了提高效率,您需要一次存储和加载寄存器集的特殊指令。摩托罗拉6

在编译器设计中,为什么调用方不能将其已用寄存器列表(在调用方保存协议的情况下会推送)传递给被调用方,而不是使用调用方或被调用方寄存器保存协议,以便被调用方可以将其已用寄存器列表与调用方使用的寄存器进行比较。然后,只有真正需要推送的寄存器才会被推送。我遗漏了什么吗?

效率很低。。。您将需要解析列表(对于每个函数!),这是完全不必要的。

这是一个有趣的想法。我认为有两件事使它不那么吸引人:

  • 无论如何,被调用方必须为最坏的情况保留堆栈空间
  • 为了提高效率,您需要一次存储和加载寄存器集的特殊指令。摩托罗拉68000(可能还有PowerPC)上有这样的指令,但它们并不流行
以下是对其工作原理的一点详细说明: 您可能希望调用方将列表作为位向量打包到机器字中。然后,您需要被调用方按位并使用其自己的列表,具有一条保存由结果位向量命名的所有寄存器的指令

因为在最坏的情况下,您必须在堆栈上保留空间,所以不会节省太多——在一个现代的、超标量的、无序的处理器上,写入同一缓存线几乎是免费的

同样,如果您真正想要的是最小化运行时的加载和存储数量,那么您只需使用所有调用者保存寄存器。这种策略还使得引发异常和先发制人地切换线程变得非常便宜,许多编译器(比如)正是出于这个原因使用这种策略的。被调用方保存寄存器是一种试图减少溢出和重新加载指令的代码大小的黑客行为。它们在许多情况下都能工作,并且节省空间,因为调用站点的数量远远超过过程定义的数量(平均而言,一个过程包含多个调用)


有关呼叫者保存和被呼叫者保存寄存器之间权衡的更多信息,请参阅。

感谢您详尽的回答!你有真正的联系吗?通过TinyURL重定向给了我一个关于cookie错误的页面,TinyURL不会透露原始内容。@Edmund:很抱歉,我一定是在工作时写下了答案,并在不知不觉中链接到了支付网站。我已经更改了链接。