GCC编译优化选项介绍

参考URL:https://blog.csdn.net/qq_31108501/article/details/51842166?

一、为什么要设计编译优化等级

1、编译优化是会更改代码的,所以需要通过不优化的方式进行直译,便于调试,确定是否是代码本身的问题,所以就有了优化和不优化的两个差异;
2、在优化中,不同的优化所得到的效果不一样,有些是牺牲时间换来空间,而有些是通过牺牲空间换来时间,所以存在不同的优化等级;
3、编译优化是非常繁杂和易错的,如果直接采用最激进的优化策略,不仅不能满足不同用户的不同需求,更重要的是最激进的策略可能会带来错误;
如果直接采用最激进的策略进行优化,那么编码阶段就必须形成规则进行约束,这么一来对开发人员的要求就很高;

综上,编译优化划分了等级,从保守到激进,即使是效率低一些也要确保不出错。

二、从源码到可执行文件

gcc 与 g++ 分别是 gnu 的 c & c++ 编译器 gcc/g++ 在执行编译工作的时候,总共需要4步:
1、预处理,生成 .i 的文件[预处理器cpp];
2、将预处理后的文件转换成汇编语言,生成文件 .s [编译器egcs];
3、有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器as];
4、连接目标代码,生成可执行程序 [链接器ld]。

所以编译优化等级主要在于第二阶段生效。

三、编译优化等级概述(差异)

编译等级共分为以下几个等级,各等级均存在不同的应用场景。

  • -O0:

无优化(默认),也是 CFLAGS 或 CXXFLAGS 中没有设置 -O 等级时的默认等级

  • -O 和-O1:

最基本的优化等级,编译器会在不花费太多编译时间(不显著增加)的同时试图 生成更快更小的代码(在编译大型程序的时候会显著增加编译时内存的使用,对于一个大的函数或功能会花费更多的时间和内存)。
由于这些优化是非常基础的,一般优化任务肯定能顺利完成。

  • -O2:

优化等级O1的进阶,包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化,此选项将 增加编译时间和目标文件的执行性能 (编译器不执行循环展开以及函数内联)。此选项是推荐的优化等级

  • -Os:

可称之为 -O2.5,在 -O2 选项的基础上(基本包含所有,除了对齐优化等),执行 优化程序空间大小 的优化选项,专门优化目标文件大小。可能产生些许问题,不推荐的优化等级。

  • -O3:

这是最高最危险的优化等级,用这个选项会延长编译代码的时间,并且在使用 gcc4.x 的系统里不应全局启用。
自从 3.x 版本以来gcc的行为已经有了极大地改变。在 3.x,-O3生成的代码也只是比-O2快一点点而已,而 gcc4.x 中还未必更快。用-O3来编译所有的软件包将产生更大体积更耗内存的二进制文件,大大增加编译失败的机会或不可预知的程序行为(包括错误)。在 gcc4.x 中使用-O3是不推荐的。

综上,没有特别要求的情况下,建议在使用的时候,直接开 -O2 的优化等级,有问题的时候调整为 -O0 进行调试
如果对自己代码比较有把握的时候,可以直接上 -O3;
如果 -O2 和 -O1 编译的目标文件大小差异较大,并且对尺寸有要求,可以上 -O1。

四、编译优化等级详述(补充)

-O1 优化选项
在不影响调试的前提下,-O1 优化选项也会添加 -fomit-frame-pointer 选项。 
在ADA编译器上,-O1 不会添加 -ftree-sra 选项,想在ADA编译器下使用该选项,必须明确的在命令行指出。

-O3 优化选项
打开所有-O2的优化选项并且增加 -finline-functions,-funswitch-loops,-fpredictive-commoning,-fgcse-after-reloadand -ftree-vectorize 优化选项。

五、小结

  • -O0 不进行任何优化。

  • -O1 优化会消耗一些的编译时间,它主要对代码的分支,常量以及表达式等进行优化。

  • -O2 尝试更多的寄存器级的优化以及指令级的优化,它会在编译期间占用更多的内存和编译时间。

  • -O3 在O2的基础上进行更多的优化,例如使用伪寄存器网络,普通函数的内联,以及针对循环的更多优化。

posted @ 2021-05-04 17:21  CristL  阅读(1682)  评论(0编辑  收藏  举报