Достаточно ли безумный уровень оптимизации gcc (-O3)?
Как часть ответа на другой вопрос, я хотел показать, что безумный уровень оптимизации gcc
(-O3
) в основном удалит все переменные, которые не использовались в main. Код был:
#include <stdio.h>
int main (void) {
char bing[71];
int x = 7;
bing[0] = 11;
return 0;
}
и gcc -O3
вывод был:
.file "qq.c"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
popl %ebp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
Теперь я вижу, что он удалил локальные переменные, но там все еще есть немало потерь. Мне кажется, что весь
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
popl %ebp
ret
раздел можно заменить на более простой:
xorl %eax, %eax
ret
Кто-нибудь знает, почему gcc
не выполняет эту оптимизацию? Я знаю, что сэкономит очень мало для main
Само по себе, но, если бы это было сделано и с обычными функциями, эффект ненужной настройки указателя стека в массивном цикле был бы значительным.
Команда, использованная для генерации сборки:
gcc -O3 -std=c99 -S qq.c
2 ответа
Вы можете включить эту конкретную оптимизацию с помощью -fomit-frame-pointer
флаг компилятора. Это делает невозможной отладку на некоторых машинах и существенно более трудной для всего остального, поэтому обычно она отключена.
Хотя ваша документация GCC может сказать, что -fomit-frame-pointer
включен на разных уровнях оптимизации, вы, вероятно, обнаружите, что это не так - вам почти наверняка придется явно включить его самостоятельно.
Включение -fomit-frame-pointer
( источник) должен избавиться от лишних манипуляций со стеком.
GCC, очевидно, оставил их, потому что они облегчают отладку (получая трассировку стека при необходимости), хотя в документах отмечается, что -fomit-frame-pointer
по умолчанию, начиная с GCC 4.6.