2016-12-30 58 views
3

考虑以下循环:编译器如何优化这一段代码

unsigned long x = 0; 
for(unsigned long i = 2314543142; i > 0; i--) 
    x+=i; 
std::cout << x << std::endl; 
当我编译这通常它需要大约6.5秒执行该循环

。但是当我使用-O3优化进行编译时,循环会在10^-6秒内执行。这怎么可能?编译器肯定不知道x的闭式表达式如何...

+2

您是否尝试过使用汇编语言输出来查看生成的代码? –

+0

不幸的是,我不知道任何程序集 – user3726947

+0

你如何计时循环? –

回答

4

如果使用优化进行编译,您并不需要知道关于程序集的所有信息,以查看编译器在编译时确定x的值。

我稍微修改了您的代码,以便能够使用在线工具Compiler Explorer,将std::cout << x << std::endl更改为extern unsigned long foo;foo = x;。没有必要,但它使输出更清洁。

与-02编译:

test(): 
     movabs rax, 2678554979246887653 
     mov  QWORD PTR foo[rip], rax 
     ret 

编译时-O0:

test(): 
     push rbp 
     mov  rbp, rsp 
     mov  QWORD PTR [rbp-8], 0 
     mov  DWORD PTR [rbp-16], -1980424154 
     mov  DWORD PTR [rbp-12], 0 
     jmp  .L2 
.L3: 
     mov  rax, QWORD PTR [rbp-16] 
     add  QWORD PTR [rbp-8], rax 
     sub  QWORD PTR [rbp-16], 1 
.L2: 
     cmp  QWORD PTR [rbp-16], 0 
     setne al 
     test al, al 
     jne  .L3 
     mov  rax, QWORD PTR [rbp-8] 
     mov  QWORD PTR foo[rip], rax 
     leave 
     ret 

另:未定义行为由于i >= 0代码的第一个版本仅仅输出:

test(): 
.L2: 
     jmp  .L2 

:-)

+0

所以看起来编译器在编译时正在计算某些东西。但是我无法在任何地方找到输出值2678554979246887653 ... – user3726947

+0

@ user3726947对不起,我不小心使用了'extern unsigned foo'而不是'extern unsigned long foo'。更新后的答案显示正确的输出值。 – gurka

3

编译器确定循环后x的值,并在输出语句中使用该值。

+0

相对于程序的长度,这必须是一个相当慢的编译。 –

+0

虽然我没有测量它,但编译时间几乎是瞬间的。当然不会超过没有-O3优化的编译时间。 – user3726947