11

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.

Mysticial
  • 464,885
  • 45
  • 335
  • 332
Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170

2 Answers2

15

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.

Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • I hadn't considered it from this perspective because the non-optimized version only uses immediate values in the subtractions. Thanks, this was very helpful. – Hunter McMillen Oct 02 '12 at 01:28
11

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.

DocMax
  • 12,094
  • 7
  • 44
  • 44
  • If `lea` does not affect flags, then how is it equivalent to `sub`? Should it not affect the flags to have the same effect as `sub`? – crisron Jan 05 '15 at 15:46
  • 1
    @crisron they are not equivalent and serve different purposes. If you don't want/need side effects, use lea, otherwise use sub – phuclv Mar 31 '16 at 06:49
  • 1
    Citation needed re efficiency? I don't think updating flags requires extra uops. And I'd assume flags are subject to register renaming, so subsequent instructions that don't look at the flags won't be delayed to wait for the flags update. – Nate Eldredge Aug 14 '21 at 23:19
  • @NateEldredge: Indeed, this sounds like nonsense. x86 CPUs need to rename FLAGS to run normal x86 code efficiently, because most integer instructions *do* update FLAGS. Moreover, integer register-file entries have room for FLAGS, so an instruction that writes an output register and FLAGS still takes 1 physical register-file entry. Pentium 4 had a false output-dependency effect with instructions like `inc` that only wrote *some* FLAGS, but `sub` writes them all. [INC instruction vs ADD 1: Does it matter?](https://stackoverflow.com/q/36510095) – Peter Cordes Aug 14 '21 at 23:43
  • [Does it cost significant resources for a modern CPU to keep flags updated?](https://stackoverflow.com/q/64817587) – Peter Cordes Aug 15 '21 at 00:02