因此,当您在编译C ++时添加优化标志时,它运行得更快,但这是如何工作的?有人能解释一下装配中究竟发生了什么吗?
答案 0 :(得分:13)
这意味着您正在使编译器在编译时执行额外的工作/分析,因此您可以在运行时获得一些额外的宝贵cpu周期的奖励。最好用一个例子来解释。
考虑这样的循环:
const int n = 5;
for (int i = 0; i < n; ++i)
cout << "bleh" << endl;
如果你在没有优化的情况下编译它,编译器将不会为你做任何额外的工作 - 为这段代码片段生成的汇编可能是比较和跳转指令的字面翻译。 (这不是最快的,也是最直接的)
但是,如果编译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;
}
如果我在x86机器上使用gcc foo.c
编译此代码时没有进行优化,我的程序集如下所示:
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
在这里,它没有优化任何东西。它用我的常量值加载寄存器并调用我的foo
函数。但是看看我是否使用-O2
标志重新编译:
movq (%rax), %rdi
leaq L_.str(%rip), %rsi
movl $150, %edx
xorb %al, %al
callq _fprintf
编译器非常智能,甚至不再调用foo
。它只是概述了它的回报值。
答案 1 :(得分:0)
在生成程序集之前,大多数优化都发生在编译器的中间表示中。你一定要看看Agner Fog的Software optimization resources。第1手册的第8章描述了编译器使用示例执行的优化。