Почему GCC не оптимизирует функции пролога и эпилога (push ebp; mov ebp, esp; ...; pop ebp)

При компиляции простой функции, которая даже не изменяет регистр ebp, GCC сохраняет значение в начале функции и затем восстанавливает то же значение в конце:

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

gcc -c -S -m32 -O3 add.c -o add.S

#add.S
    .file   "add.c"
    .text
    .p2align 4,,15
.globl add
    .type   add, @function
add:
    pushl   %ebp
    movl    %esp, %ebp
    movl    12(%ebp), %eax
    addl    8(%ebp), %eax
    popl    %ebp
    ret
    .size   add, .-add
    .ident  "GCC: (GNU) 4.4.6"
    .section        .note.GNU-stack,"",@progbits

Казалось бы, простая оптимизация - оставить ebp нетронутым, рассчитать смещения относительно esp и сохранить 3 инструкции.

Почему GCC не делает этого?

Спасибо,

Эндрю

1 ответ

Решение

Такие инструменты, как отладчики и обходчики стека, привыкли ожидать, что в коде будет пролог, создающий указатель кадра, и он не сможет понять код, в котором его нет. Со временем ограничение было снято.

Сам компилятор без труда генерирует код без указателя кадра, и вы можете попросить его удалить с помощью -fomit-frame-pointer, Я полагаю, что последние версии gcc (~4.8) и gcc на x86-64 по умолчанию опускают указатель кадра.

Другие вопросы по тегам