1.8. PRINTF() WITH SEVERAL ARGUMENTS
Optimizing Keil 6/2013 (ARM mode) + let’s remove return
Let’s rework example slightly by removingreturn 0:
#include <stdio.h>
void main()
{
printf("a=%d; b=%d; c=%d", 1, 2, 3);
};
The result is somewhat unusual:
Listing 1.51: Optimizing Keil 6/2013 (ARM mode)
.text:00000014 main
.text:00000014 03 30 A0 E3 MOV R3, #3
.text:00000018 02 20 A0 E3 MOV R2, #2
.text:0000001C 01 10 A0 E3 MOV R1, #1
.text:00000020 1E 0E 8F E2 ADR R0, aADBDCD ; "a=%d; b=%d; c=%d\n"
.text:00000024 CB 18 00 EA B __2printf
This is the optimized (-O3) version for ARM mode and this time we seeBas the last instruction instead
of the familiarBL. Another difference between this optimized version and the previous one (compiled
without optimization) is the lack of function prologue and epilogue (instructions preserving theR0andLR
registers values). TheBinstruction just jumps to another address, without any manipulation of theLR
register, similar toJMPin x86. Why does it work? Because this code is, in fact, effectively equivalent to
the previous. There are two main reasons: 1) neither the stack norSP(thestack pointer) is modified; 2)
the call toprintf()is the last instruction, so there is nothing going on afterwards. On completion, the
printf()function simply returns the control to the address stored inLR. Since theLRcurrently stores
the address of the point from where our function has been called then the control fromprintf()will be
returned to that point. Therefore we do not have to saveLRbecause we do not have necessity to modify
LR. And we do not have necessity to modifyLRbecause there are no other function calls exceptprintf().
Furthermore, after this call we do not to do anything else! That is the reason such optimization is possible.
This optimization is often used in functions where the last statement is a call to another function. A similar
example is presented here:1.15.1 on page 154.
ARM64
Non-optimizing GCC (Linaro) 4.9
Listing 1.52: Non-optimizing GCC (Linaro) 4.9
.LC1:
.string "a=%d; b=%d; c=%d"
f2:
; save FP and LR in stack frame:
stp x29, x30, [sp, -16]!
; set stack frame (FP=SP):
add x29, sp, 0
adrp x0, .LC1
add x0, x0, :lo12:.LC1
mov w1, 1
mov w2, 2
mov w3, 3
bl printf
mov w0, 0
; restore FP and LR
ldp x29, x30, [sp], 16
ret
The first instructionSTP(Store Pair) savesFP(X29) andLR(X30) in the stack. The secondADD X29, SP,
0 instruction forms the stack frame. It is just writing the value ofSPinto X29.