gcc究竟如何做优化?

Iva*_*van 5 c optimization gcc compiler-optimization

为了知道gcc究竟如何进行优化,我编写了两个用-O2编译的程序,但是汇编代码有一些区别.在我的程序中,我想在循环中输出"hello",并在每个输出之间添加一些延迟.这两个程序仅用于说明我的问题,我知道我可以在程序1中使用volatile或asm来实现我的目的.

计划1

#include <stdio.h>

int main(int argc, char **argv)
{
    unsigned long i = 0;
    while (1) {
        if (++i > 0x1fffffffUL) {
            printf("hello\n");
            i = 0;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用-O2编译,汇编代码是:

Disassembly of section .text.startup:

00000000 <_main>:
#include <stdio.h>

int main(int argc, char **argv)
{
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 10                sub    $0x10,%esp
   9:   e8 00 00 00 00          call   e <_main+0xe>
   e:   66 90                   xchg   %ax,%ax
  10:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
  17:   e8 00 00 00 00          call   1c <_main+0x1c>
  1c:   eb f2                   jmp    10 <_main+0x10>
  1e:   90                      nop
  1f:   90                      nop
Run Code Online (Sandbox Code Playgroud)

计划2

int main(int argc, char **argv)
{
    unsigned long i = 0;
    while (1) {
        if (i > 0x1fffffffUL) {
            printf("hello\n");
            i = 0;
        }
        i++;
    }
}
Run Code Online (Sandbox Code Playgroud)

用-O2编译,汇编代码是:

Disassembly of section .text.startup:

00000000 <_main>:
#include <stdio.h>

int main(int argc, char **argv)
{
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 10                sub    $0x10,%esp
   9:   e8 00 00 00 00          call   e <_main+0xe>
   e:   31 c0                   xor    %eax,%eax
  10:   83 c0 01                add    $0x1,%eax
  13:   3d ff ff ff 1f          cmp    $0x1fffffff,%eax
  18:   76 f6                   jbe    10 <_main+0x10>
  1a:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
    while (1) {
        if (i > 0x1fffffffUL) {
            printf("hello\n");
            i = 0;
        }
        i++;
  21:   e8 00 00 00 00          call   26 <_main+0x26>

int main(int argc, char **argv)
{
    unsigned long i = 0;
    while (1) {
        if (i > 0x1fffffffUL) {
  26:   31 c0                   xor    %eax,%eax
  28:   eb e6                   jmp    10 <_main+0x10>
            printf("hello\n");
  2a:   90                      nop
  2b:   90                      nop
  2c:   90                      nop
  2d:   90                      nop
  2e:   90                      nop
  2f:   90                      nop
Run Code Online (Sandbox Code Playgroud)

在程序1中,增加了i优化,但它不在程序2中.为什么会发生这种情况?gcc在为这两个程序优化-O2时使用了哪些规则?

Dev*_*lar 9

问"为什么"关于优化通常是浪费时间,因为那里没有"规则"通过优化操作-比其他"好像":优化程序可能无法更改代码一致的观察到的行为.

你的程序的"可观察行为"是反复打印"你好".

在您的第一个程序中,计数被优化掉,使得可观察的行为更快地发生.这是优化器的工作.请高兴您的代码现在更高效!

在你的第二个程序中,计数没有被优化掉,因为不知何故优化器 - 在这个版本的这个编译器中有这个设置 - 并没有看到它没有它.为什么?谁知道(除了编译器的优化器模块的维护者)?

如果您希望的行为是在输出之间有延迟,请使用类似thrd_sleep()的内容.空计数循环是在C64上延迟BASIC 2.0程序的一种方法,但它们不应该在C中使用,原因在于您刚才观察到的:您永远不知道优化程序的作用.