优化代码时,编译器在汇编中做了什么?即-O2标志

atk*_*yla 10 c++ compiler-optimization

因此,当您在编译C++时添加优化标志时,它运行得更快,但这是如何工作的?有人能解释一下装配中究竟发生了什么吗?

yam*_*tes 13

这意味着您正在使编译器在编译时执行额外的工作/分析,因此您可以在运行时获得一些额外的宝贵cpu周期的奖励.可能最好用一个例子来解释.

考虑这样的循环:

const int n = 5;
for (int i = 0; i < n; ++i)
  cout << "bleh" << endl;
Run Code Online (Sandbox Code Playgroud)

如果你在没有优化的情况下编译它,编译器将不会为你做任何额外的工作 - 为这段代码片段生成的程序集可能是比较和跳转指令的字面翻译.(这不是最快的,只是最直接的)

但是,如果编译WITH优化,编译器可以轻松地进行inline此循环,因为它知道上限不能因为n而改变const.(即它可以直接复制重复代码5次,而不是比较/检查终止循环条件).

这是另一个优化函数调用的例子.以下是我的整个计划:

#include <stdio.h>
static int foo(int a, int b) {
  return a * b;
} 


int main(int argc, char** argv) {
  fprintf(stderr, "%d\n", foo(10, 15));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我gcc foo.c在我的x86机器上没有使用优化编译此代码,我的程序集如下所示:

movq    %rsi, %rax
movl    %edi, -4(%rbp)
movq    %rax, -16(%rbp)
movl    $10, %eax      ; these are my parameters to
movl    $15, %ecx      ; the foo function
movl    %eax, %edi
movl    %ecx, %esi
callq   _foo
; .. about 20 other instructions ..
callq   _fprintf
Run Code Online (Sandbox Code Playgroud)

在这里,它没有优化任何东西.它用我的常量值加载寄存器并调用我的foo函数.但看看我是否用-O2旗帜重新编译:

movq    (%rax), %rdi
leaq    L_.str(%rip), %rsi
movl    $150, %edx
xorb    %al, %al
callq   _fprintf
Run Code Online (Sandbox Code Playgroud)

编译器非常智能,甚至foo不再调用.它只是概述了它的回报价值.