简体   繁体   中英

Why does GCC produce stack preservation instructions when they're not necessary?

I'm compiling the following simple demonstration function:

int add(int a, int b) {
    return a + b;
}

Naturally this function would be inlined, but let's assume that it's dynamically linked or not inlined for some other reason. With optimization disabled, the compiler produces the expected code:

00000000 <add>:
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   8b 45 0c                mov    eax,DWORD PTR [ebp+0xc]
   6:   03 45 08                add    eax,DWORD PTR [ebp+0x8]
   9:   5d                      pop    ebp
   a:   c3                      ret

Since there are no function calls inside this function, the instructions at 0, 1 and 9 seemingly have no purpose. Since optimization is disabled, this is acceptable.

However, when compiling while optimizing for size with -Os -s , the exact same code is produced. It seems rather wasteful to increase the size of the function by 66% with these options.

Why is the code not optimized to the following?

00000000 <add>:
   0:   8b 45 0c                mov    eax,DWORD PTR [esp+0x8]
   3:   03 45 08                add    eax,DWORD PTR [esp+0x4]
   6:   c3                      ret

Does the compiler just not consider this worth optimizing or is it related to other details like function alignment?

This is done to preserve the ability of the debugger to step through your code.

If you really want to disable this try -fomit-frame-pointer .

Compiling your above code using -Os -fomit-frame-pointer -S -masm=intel gave this:

    .file   "frame.c"
    .intel_syntax noprefix
    .text
    .globl  _add
    .def    _add;   .scl    2;  .type   32; .endef
_add:
    mov eax, DWORD PTR [esp+8]
    add eax, DWORD PTR [esp+4]
    ret
    .ident  "GCC: (rev0, Built by MinGW-builds project) 4.8.0"

The value of EBP is not known when the function enters. Code could use mov eax,dword ptr [esp+8] and not bother with the BP register, but many debugging tools assume that each local variable is at a fixed offset relative to some register. Even if a compiler could keep track of things that were pushed on the stack and adjust indexing offsets appropriately, debuggers would likely be unable to do so.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM