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.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With