Когда я должен опустить указатель кадра?

Есть ли существенная оптимизация при пропуске указателя кадра? Если я правильно понял, прочитав эту страницу, -fomit-frame-pointer используется, когда мы хотим избежать сохранения, настройки и восстановления указателей кадров.

Это делается только для каждого вызова функции, и если да, то стоит ли избегать нескольких инструкций для каждой функции? Разве это не тривиально для оптимизации? Каковы реальные последствия использования этой опции помимо ограничений отладки?

Я скомпилировал следующий код C с и без этой опции

int main(void)
{
        int i;

        i = myf(1, 2);
}

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

,

# gcc -S -fomit-frame-pointer code.c -o withoutfp.s
# gcc -S code.c -o withfp.s

,

diff -u При использовании двух файлов был обнаружен следующий код сборки:


--- withfp.s    2009-12-22 00:03:59.000000000 +0000
+++ withoutfp.s 2009-12-22 00:04:17.000000000 +0000
@@ -7,17 +7,14 @@
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
-       pushl   %ebp
-       movl    %esp, %ebp
        pushl   %ecx
-       subl    $36, %esp
+       subl    $24, %esp
        movl    $2, 4(%esp)
        movl    $1, (%esp)
        call    myf
-       movl    %eax, -8(%ebp)
-       addl    $36, %esp
+       movl    %eax, 20(%esp)
+       addl    $24, %esp
        popl    %ecx
-       popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
@@ -25,11 +22,8 @@
 .globl myf
        .type   myf, @function
 myf:
-       pushl   %ebp
-       movl    %esp, %ebp
-       movl    12(%ebp), %eax
-       addl    8(%ebp), %eax
-       popl    %ebp
+       movl    8(%esp), %eax
+       addl    4(%esp), %eax
        ret
        .size   myf, .-myf
        .ident  "GCC: (GNU) 4.2.1 20070719 

Может ли кто-нибудь пролить свет на ключевые моменты приведенного выше кода, где -fomit-frame-pointer действительно имеет значение?

Редактировать: objdumpвыход заменен на gcc -S"s

4 ответа

Решение

-fomit-frame-pointer позволяет использовать один дополнительный регистр для общего пользования. Я бы предположил, что это действительно серьезная проблема для 32-битной x86, которая немного страдает от регистров.*

Можно было бы ожидать, что EBP больше не будет сохраняться и корректироваться при каждом вызове функции, и, возможно, некоторое дополнительное использование EBP в обычном коде и меньшее количество операций стека в тех случаях, когда EBP используется в качестве регистра общего назначения.

Ваш код слишком прост, чтобы увидеть какую-либо выгоду от такого рода оптимизации - вы не используете достаточно регистров. Кроме того, вы не включили оптимизатор, который может понадобиться, чтобы увидеть некоторые из этих эффектов.

* Регистры ISA, а не регистры микроархитектуры.

Единственный недостаток - это отладка гораздо сложнее.

Основным преимуществом является то, что существует один дополнительный регистр общего назначения, который может существенно повлиять на производительность. Очевидно, что этот дополнительный регистр используется только тогда, когда это необходимо (вероятно, в вашей очень простой функции это не так); в некоторых функциях это имеет большее значение, чем в других.

Часто вы можете получить более значимый код сборки из GCC, используя -S Аргумент для вывода сборки:

$ gcc code.c -S -o withfp.s
$ gcc code.c -S -o withoutfp.s -fomit-frame-pointer
$ diff -u withfp.s withoutfp.s

GCC не заботится об адресе, поэтому мы можем сравнивать фактические инструкции, сгенерированные напрямую. Для вашей функции листьев это дает:

 myf:
-       pushl   %ebp
-       movl    %esp, %ebp
-       movl    12(%ebp), %eax
-       addl    8(%ebp), %eax
-       popl    %ebp
+       movl    8(%esp), %eax
+       addl    4(%esp), %eax
    ret

GCC не генерирует код для вставки указателя кадра в стек, и это изменяет относительный адрес аргументов, передаваемых функции в стеке.

Профилируйте свою программу, чтобы видеть, есть ли существенная разница.

Затем профилируйте процесс разработки. Отладка проще или сложнее? Вы тратите больше времени на разработку или меньше?

Оптимизация без профилирования - пустая трата времени и денег.

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