Когда я должен опустить указатель кадра? - PullRequest
28 голосов
/ 22 декабря 2009

Есть ли существенная оптимизация при пропуске указателя кадра? Если я правильно понял, прочитав эту страницу, -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 ]

29 голосов
/ 22 декабря 2009

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

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

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

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

9 голосов
/ 22 декабря 2009

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

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

7 голосов
/ 22 декабря 2009

Часто вы можете получить более значимый код сборки из 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 не генерирует код для помещения указателя кадра в стек, и это изменяет относительный адрес аргументов, передаваемых функции в стеке.

5 голосов
/ 22 декабря 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...