I noticed that when optimizations are turned off, GCC (version 13.1.1 20230714) when asked to assemble the below C program, loads the address of the string (i.e., .string "HI" in the assembler output) into rax and then into rdi before calling the function -
#include <stdio.h>
int main() {
printf("HI\n");
return 0;
}
The assembler output with optimizations turned off (-O0) -
...
lea rax, .LC0[rip]
mov rdi, rax
call puts@PLT
....
And with optimizations turned on (for -O1, -O2, and -O3) -
...
lea rdi, .LC0[rip]
call puts@PLT
mov eax, 0
...
I understand that I can expect the versions with optimizations to do things more...optimally. But, there is nothing about the C code that I wrote which makes the unoptimized assembly a more "one-to-one" mapping of assembly to C so I don't see why gcc should default to loading the address into rax. In any case, it is already not the case that gcc is not optimizing anything since it replaced the call to printf with a call to puts.
Can someone help explain to me why gcc does this? Does it have any advantage or is it simply not worth making the -O0 compilation do something like this? If this is the default behaviour for all function calls (before optimization), what is the reason that gcc loads the first argument into rax, shouldn't loading the first argument directly into rdi be the sensible default?
GCC version - gcc (GCC) 13.1.1 20230714
Platform/OS - Linux 6.4.3-arch1-2 x86_64 GNU/Linux
Compilation command - gcc -O0/1/2/3 -S -masm=intel load.c