Why does GCC emit “lea” instead of “sub” for subtraction?
-
12-12-2019 - |
Question
I am looking at some assembly that was generated by disassembling some C programs and I am confused by a single optimization that I see repeated frequently.
When I have no optimizations on the GCC compiler uses the subl
instruction for subtraction, but when I do have optimizations turned on (-O3
to be precise) the compiler uses a leal
instruction instead of subtraction, example below:
without optimizations:
83 e8 01 subl $0x1, %eax
with optimizations
8d 6f ff leal -0x1(%edi), %ebp
Both of these instructions are 3 bytes long, so I am not seeing an optimization here. Could someone help me out and try to explain the compiler's choice ?
Any help would be appreciated.
Solution
It's hard to tell without seeing the original C code that produces this.
But if I had to guess, it's because the leal
allows the subtraction to be done out-of-place without destroying the source register.
This can save an extra register move.
The first example:
83 e8 01 subl $0x1, %eax
overwrites %eax
thereby destroying the original value.
The second example :
8d 6f ff leal -0x1(%edi), %ebp
stores %edi - 1
into %ebp
. %edi
is preserved for future use.
OTHER TIPS
Keep in mind also that lea
does not affect the flags whereas sub
does. So if the ensuing instructions do not depend on the flags being updated by the subtraction then not updating the flags will be more efficient as well.