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

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

28
задан PetrosB 9 January 2010 в 12:27
поделиться

4 ответа

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

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

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

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

29
ответ дан 28 November 2019 в 03:15
поделиться

Единственным недостатком его исключения является то, что отладка намного сложнее.

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

9
ответ дан 28 November 2019 в 03:15
поделиться

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

7
ответ дан 28 November 2019 в 03:15
поделиться

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

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

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

5
ответ дан 28 November 2019 в 03:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: