gcc疯狂优化级别(-O3)不够疯狂吗?

时间:2011-02-23 02:01:47

标签: optimization gcc stackframe

作为回答另一个问题的一部分,我想表明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 个答案:

答案 0 :(得分:9)

您可以使用-fomit-frame-pointer编译器标志启用该特定优化。这样做会使得某些机器上的调试变得不可能,而其他所有机器上的调试也变得更加困难,这就是它通常被禁用的原因。

虽然您的GCC文档可能会说-fomit-frame-pointer已在各种优化级别启用,但您可能会发现情况并非如此 - 您几乎肯定必须自己明确启用它。

答案 1 :(得分:6)

启用-fomit-frame-pointersource)应该摆脱额外的堆栈操作。

GCC显然已将其留下,因为它们有助于调试(在需要时获取堆栈跟踪),尽管文档指出-fomit-frame-pointer是从GCC 4.6开始的默认值。