Почему 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 по умолчанию опускают указатель кадра.