5

我想研究某些 C/C++ 特性是如何转换为程序集的,我创建了以下文件:

struct foo {
    int x;
    char y[0];
};

char *bar(struct foo *f)
{
    return f->y;
}

然后我用gcc -S(也试过用g++ -S)编译了这个,但是当我查看汇编代码时,我很失望地发现 bar 函数中有一个微不足道的冗余,我认为gcc应该能够优化掉:

_bar:
Leh_func_begin1:
        pushq   %rbp
Ltmp0:
        movq    %rsp, %rbp
Ltmp1:
        movq    %rdi, -8(%rbp)
        movq    -8(%rbp), %rax
        movabsq $4, %rcx
        addq    %rcx, %rax
        movq    %rax, -24(%rbp)
        movq    -24(%rbp), %rax
        movq    %rax, -16(%rbp)
        movq    -16(%rbp), %rax
        popq    %rbp
        ret
Leh_func_end1:

除其他外,线条

        movq    %rax, -24(%rbp)
        movq    -24(%rbp), %rax
        movq    %rax, -16(%rbp)
        movq    -16(%rbp), %rax

看起来毫无意义的多余。gcc(可能还有其他编译器)有什么理由不能/不优化这个吗?

4

2 回答 2

11

我认为 gcc 应该能够优化掉。

gcc 手册

在没有任何优化选项的情况下,编译器的目标是降低编译成本并使调试产生预期的结果。

换句话说,除非您要求,否则它不会优化。当我使用该标志打开优化时-O3,gcc 4.4.6 会生成更高效的代码:

bar:
.LFB0:
        .cfi_startproc
        leaq    4(%rdi), %rax
        ret
        .cfi_endproc

有关更多详细信息,请参阅手册中的控制优化的选项。

于 2012-05-19T06:49:44.760 回答
8

编译器在没有优化的情况下生成的代码通常是直接的逐条指令翻译,这些指令不是程序的指令,而是可能引入冗余的中间表示的指令。

如果您希望汇编没有此类冗余说明,请使用gcc -O -S

您所期望的优化称为窥孔优化。编译器通常有很多这些,因为与更多的全局优化不同,它们应用起来很便宜并且(通常)不会冒险使代码变得更糟——至少如果在编译结束时应用的话。

这篇博文中,我提供了一个示例,当源代码中的整数类型是 64 位但只有最低的 32 位结果很重要时,GCC 和 Clang 都可以生成更短的 32 位指令。

于 2012-05-19T06:49:42.180 回答