16.1.5 消除公共子表达式

和该话题相关的 GCC 选项: -fgcse 和其它包含 cse 这个字符串的选项。

如果两个表达式中有相同的部分,不会导致该部分被计算两次。也就是说对这种公共部分进行预计算,把结果保存在变量中,然后在两个表达式中使用该变量,从优化角度来讲,这样做没什么用处。

在列表 16-8 的例子中,子表达式 x*x + 2*x 就只会被计算一次,而不像直观的感受那样。

Listing 16-8.common_subexpression.c

#include <stdio.h>

__attribute__ ((noinline))
    void test(int x) {
        printf("%d %d",
                x*x + 2*x + 1,
                x*x + 2*x - 1 );
    }

int main(int argc, char** argv) {
    test( argc );
    return 0;
}

列表 16-9 是编译后的机器码,可以作为我们上述结论的佐证,对 x*x + 2*x 这个公共表达式不会计算两次。

Listing 16-9.common_subexpression.asm

0000000000400516 <test>:
; rsi = x + 2
400516:       8d 77 02                           lea       esi,[rdi+0x2]
400519:       31 c0                              xor       eax,eax
40051b:       0f af f7                           imul      esi,edi
; rsi = x*(x+2)
40051e:       bf b4 05 40 00                     mov       edi,0x4005b4
; rdx = rsi-1 = x*(x+2) - 1
400523:       8d 56 ff                           lea       edx,[rsi-0x1]
; rsi = rsi + 1 = x*(x+2) - 1
400526:       ff c6                              inc       esi
400528:       e9 b3 fe ff ff                     jmp       4003e0 <printf@plt>

我们怎么活用这套结论呢?不要害怕在你漂亮的公式中出现一样的子表达式,编译器会高效地对它们进行计算。尽量从代码的可读性角度去考虑这种问题。

results matching ""

    No results matching ""