【问题标题】:Why does ARM say that "A link register supports fast leaf function calls"为什么ARM说“链接寄存器支持快速叶函数调用”
【发布时间】:2016-11-01 03:48:28
【问题描述】:

我最近接触了链接寄存器和叶子函数的概念。

我从之前的 SO 中了解到,LR 告诉了代码在执行期间之前的位置。我还知道叶函数是位于函数调用层次结构末尾的函数。

ARM wikipedia page says:

链接寄存器支持快速叶函数调用。

为什么这个说法是正确的?我查看了 ARMARM(架构参考手册),链接寄存器的信息很少。

【问题讨论】:

  • 请注意,现代微架构往往具有硬件返回堆栈,可预测函数将返回的位置,从而允许通过返回进行推测执行。即使没有链接寄存器的处理器实际上也不会等待从内存中重新加载返回地址。

标签: assembly arm cpu-architecture instruction-set


【解决方案1】:

在某些架构(如x86、x86_64)上,函数的返回地址总是存储在堆栈中,调用函数意味着访问主存:

  • 调用时写入堆栈;

  • 返回时从堆栈中读取。

相反,如果您的架构/ABI 可以在不使用主存的情况下跳转/返回,并且被调用方的参数和返回值也可以在寄存器中传递,那么叶函数的调用和返回可以不使用涉及 RAM。

如果叶子函数足够简单,它可以在完全不接触 RAM 的情况下执行:

int callee(int a, int b)
{
  return a + b;
}

int caller(int a, int b, int c, int d)
{
  return callee(a,b) + calle(c,d);
}

给出(每个函数由clang -target arm-eabi -S -o- -O3单独编译):

callee:
  add   r0, r1, r0
  bx    lr
caller:
  .save {r4, r5, r6, r10, r11, lr}
  push  {r4, r5, r6, r10, r11, lr}
  .setfp    r11, sp, #16
  add   r11, sp, #16
  mov   r4, r3
  mov   r5, r2
  bl    callee
  mov   r6, r0
  mov   r0, r5
  mov   r1, r4
  bl    callee
  add   r0, r0, r6
  pop   {r4, r5, r6, r10, r11, lr}
  bx    lr

注意我们如何避免访问callercalee 的核心内存。

【讨论】:

  • 为什么说函数的返回类型?链接寄存器存储的是返回地址,不是返回值也不是返回类型。
  • @blatinox,我的意思是“地址”:)
  • @Notlikethat:哦,对了,那个项目符号列表很古老。标题说与英特尔 80286 和摩托罗拉 68020 等处理器相比,其他要点之一是大多数指令的条件执行减少了分支开销并弥补了分支预测器的不足我>。在这种情况下,是的,这是完全有道理的。我之前的评论早于 OP 采购报价,因此我们可以看到该上下文。我在想它仍然被列为一些 ARM 文档中的现代卖点。
  • @Peter ...也就是说,对于像 Alpha 或 POWER 这样的设计为快速的架构,这仍然是一个有效的问题。 Alpha 竭尽全力避免潜在的管道互锁,以至于它甚至没有专用的链接寄存器(经过检查,我现在爱上了 Alpha 架构手册中的这个块:”可以通过以下方式建立 PC 相对寻址能力:BR Rx,<label on the following line>")
  • @Notlikethat 实际上这听起来更糟。编码空间的浪费,因为调用约定无论如何都必须定义一个特定的链接寄存器,而现在实现返回地址预测器会变得更加困难。
【解决方案2】:

原因是这意味着在调用叶函数时,返回地址不必被压入堆栈(因为它存储在链接寄存器中)。这应该比在没有链接寄存器的处理器中将返回地址推入堆栈更快(但不确定它实际上是否更快)。

但是,在某些情况下,叶函数无论如何都必须将数据保存到堆栈中。例如,具有许多变量的叶函数可能需要使用堆栈来存储它们或保存链接寄存器以释放临时寄存器。

【讨论】:

  • 链接寄存器在哪个ABI中可以作为临时寄存器使用?
  • @blatinox 正常的 ABI。非叶函数返回的正常方式是从堆栈中弹出返回地址(不恢复链接寄存器),因此调用者不能假设链接寄存器保留它已放入寄存器中的值。以这种方式使用链接寄存器是很常见的。
猜你喜欢
  • 2011-03-31
  • 2015-07-10
  • 2023-01-31
  • 2012-01-18
  • 2014-01-18
  • 2011-11-23
  • 1970-01-01
  • 2014-10-21
  • 1970-01-01
相关资源
最近更新 更多