gcc -O0 -O1 -O2 -O3 -Os 编译优化等级

Posted Li-Yongjun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gcc -O0 -O1 -O2 -O3 -Os 编译优化等级相关的知识,希望对你有一定的参考价值。

优化等级

gcc 提供了大量优化等级,用来对编译时间目标文件大小执行效率三个维度进行不同的取舍和平衡

  • -O0,最少的优化。(这是默认的编译选项)(可以最大程度上配合产生代码调试信息,可以在任何代码行打断点,特别是死代码处)
  • -O-O1,有限优化。(编译时占用稍微多的时间和相当大的内存,减少代码生成尺寸、缩短执行时间)(去除无用的 inline 和无用的 static 函数、死代码消除等,在影响到调试信息的地方均不进行优化,在适当的代码体积和充分的调试之间平衡,代码编写阶段最常用的优化等级)
  • -O2,高度优化。(在 -O1 的基础上,尝试更多的寄存器级的优化以及指令级的优化)(调试信息不友好,有可能会修改代码和函数调用执行流程,自动对函数进行内联)
  • -O3,最大程度优化。(在 -O2 的基础上,针对循环进行更多的优化,更激进的函数内陆等)
  • -Os,相当于 -O2.5。使用了所有 -O2 的优化选项,但又不缩减代码尺寸的方法。

实战演练

使用 STM32CubeMX 新建一个简单 demo,并用 Keil5 打开,使用 STM32CubeMX 创建的工程,gcc 编译优化等级默认为 -O3。
在 main() 函数里有一句 int a = 100;,打开仿真,发现这句被编译成的汇编语句为

MOVS r0,#0x64

即,将 r0 寄存器赋值为 100,就没有然后了。


我们手动将优化等级改为 -O0,重新看 int a = 100; 对应的汇编语句,发现是两句

MOVS r0,#0x64
STR  r0,[sp,#0x00]

即,将 r0 寄存器赋值为 100,然后将 r0 寄存器中的值设置到 sp + 0x00 对应的内存位置,sp 即为栈顶。因为 a 是 main() 函数中第一个定义的变量,所以正好处于栈顶。

两者对比,-O3 优化的结果是:int a = 100; 语句并没有将 a 对应的内存真正的赋值为 100,而是等到后面使用时再进行赋值(已证实),这样做的好处是,如果后续没有对 a 的访问,真正的赋值工作可以不用做了。
-O0 由于没有优化,所以 int a = 100; 语句就乖乖地将 a 对应的内存真正的赋值 100 了。

调试的时候,要使用 -O0,不然你大概率会发现程序并不是按照你预期的顺序执行的。

以上是关于gcc -O0 -O1 -O2 -O3 -Os 编译优化等级的主要内容,如果未能解决你的问题,请参考以下文章

#ifdef 标志来区分 gcc 和 g++ 编译器? [复制]

如何将javascript代码编译为c++或java

如何在ubuntu16.04创建12.04 gcc编译环境

gcc基本功能以及常见编译选项

gcc

aarch64-linux-gnu-g++ 交叉编译为 arm64 错误