Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ARM say that "A link register supports fast leaf function calls"

I have came across the concepts of link register and leaf functions recently.

I understand from previous SO reads that the LR tells where the code was previously during execution. I also got to know that a leaf function is a function which comes at the end of the function call hierarchy.

The ARM wikipedia page says:

A link register supports fast leaf function calls.

Why is this claim true? I looked at the ARMARM (Architecture Reference Manual), and the information on the link register is minimal.

like image 799
achoora Avatar asked Jun 29 '16 12:06

achoora


2 Answers

On some architectures (such as x86, x86_64), the return address of a function is always stored on the stack and calling a function implies accessing the main memory:

  • a write to the stack when calling;

  • a read from the stack when returning.

In contrast, if your architecture/ABI can jump/return without using the main memory and the parameters and return values of the callee can be passed in registers as well, the call and return to/from leaf functions can be done without involving RAM.

If the leaf function is simple enough, it might execute without touching RAM at all:

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);
}

gives (each function compiled separately by 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

Notice how we can avoid accessing the memory in the core of caller and in calee.

like image 154
ysdx Avatar answered Oct 10 '22 20:10

ysdx


The reason is that this means that when calling the leaf function the return address does not have to be pushed to the stack (since it's stored in the link register). This is supposed to be faster than pushing the return address to the stack as you do in processors that doesn't have a link register (but it's not certain that it is actually faster).

However there are situations where the leaf function must save data to the stack anyway. For example a leaf function with many variables may need to use the stack to either store them or to save the link register to free up temporary registers.

like image 31
skyking Avatar answered Oct 10 '22 20:10

skyking