编译器在程序集中优化代码时会做什么?即O2标志
What does the compiler do in assembly when optimizing code? ie -O2 flag
因此,当您在编译C++时添加优化标志时,它会运行得更快,但这是如何工作的呢?有人能解释一下大会到底发生了什么吗?
这意味着你让编译器在编译时做额外的工作/分析,所以你可以在运行时获得一些额外宝贵的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, "%dn", 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
。它只是内联它的返回值。
在生成程序集之前,大多数优化都发生在编译器的中间表示中。你绝对应该看看AgnerFog的软件优化资源。第一本手册的第8章通过实例描述了编译器执行的优化。
相关文章:
- -Wlifetime 标志的目的是什么?
- 标志 |= f == s[i],这个语句会做什么?
- 可以在 macOS 上启用的最低支持的 SSE 标志是什么?
- Windows(Visual Studio)中的-fpermssive标志的替代方案是什么
- 什么时候关闭__strict_ansi__标志是不安全的
- ms-extensions标志对gcc到底有什么作用?
- 链接标志对静态库意味着什么
- printf 的长度修饰符标志有什么意义?
- 用Accept4()设置SOCK_CLOEXEC标志的目的是什么?
- "-Bdynamic"编译标志有什么作用?
- 在 C++ 中,我可以将什么用作 int 数组中的标志
- 编译器在程序集中优化代码时会做什么?即O2标志
- 在 g++ 中生成 "-L" 和 -rpath 标志的等效函数是什么
- 解码像 FAST 这样的数据协议的快速方法是什么,其中数据以字节为单位编码,并将位作为存在标志
- 什么是建议的一组编译器标志,以帮助减少错误
- 什么是-D编译器标志C++(clang,GNU,MSVC)
- 我应该使用什么标志来强制执行一个好的C++11样式
- g++的json精神链接器标志是什么
- 在g++中包含额外的链接器标志有什么害处吗?
- 编译标志-static对gcc真正意味着什么