问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

GCC编译器优化技巧全解析:从基础到进阶

创作时间:
作者:
@小白创作中心

GCC编译器优化技巧全解析:从基础到进阶

引用
知乎
16
来源
1.
https://zhuanlan.zhihu.com/p/616334602
2.
https://m.blog.csdn.net/lkkey80/article/details/41980087
3.
https://blog.csdn.net/weixin_36847857/article/details/140510388
4.
https://m.blog.csdn.net/cskywit/article/details/5925478
5.
https://blog.csdn.net/u013318019/article/details/127418816
6.
https://zhuanlan.zhihu.com/p/384160632
7.
https://runebook.dev/en/articles/gcc/optimize-options
8.
https://toxigon.com/optimizing-c-code-with-gcc
9.
https://gcc.gnu.org/gcc-13/changes.html
10.
https://www.w3cschool.cn/doc_gcc_6/gcc_6-gcov-and-optimization.html
11.
https://www.cnblogs.com/JohnShao/archive/2011/10/10/2206567.html
12.
https://www.coonote.com/note/gcc-o1-o2-o3.html
13.
https://runebook.dev/en/articles/gcc/other-builtins
14.
https://codezup.com/c-performance-optimization-compiler-flags/
15.
https://developers.redhat.com/articles/2023/06/21/new-c-features-gcc-13#additional_updates
16.
https://developers.redhat.com/articles/2023/06/21/new-c-features-gcc-13#c__23_features

GCC(GNU Compiler Collection)是广泛使用的开源编译器套件,支持C、C++等多种编程语言。通过合理设置优化选项,可以显著提升程序的执行效率和性能。本文将详细介绍GCC的优化技巧,从基础优化级别到高级代码优化,再到最新的GCC 13特性,帮助开发者掌握如何充分利用GCC编译器的优化能力。

01

优化级别选择

GCC提供了多个优化级别,通过-O选项进行控制。每个级别都有其特点和适用场景:

  • -O0:不进行任何优化,适合调试使用。这个级别保持代码结构与源代码最接近,便于定位问题。

  • -O1:基本优化级别,平衡了编译时间和执行效率。它会启用一些简单的优化,如常量折叠、死代码消除等,但不会进行可能影响代码大小的优化。

  • -O2:更高级别的优化,启用了几乎所有的不涉及空间-速度权衡的优化选项。这是大多数应用程序的推荐选择,它在性能和编译时间之间取得了良好平衡。

  • -O3:最高级别的优化,启用了所有-O2的优化,并添加了一些可能增加编译时间的优化,如循环展开和函数内联。适用于对性能要求极高的场景,但可能会导致代码体积增大。

  • -Os:优化代码大小,适用于嵌入式系统或对内存使用敏感的场景。它会优先考虑减小代码体积,而不是提高执行速度。

  • -Og:优化调试体验,在保持代码可调试性的同时进行一些性能优化。适合在开发阶段使用。

例如,要使用-O2优化级别编译程序,可以使用以下命令:

gcc -O2 -o myprogram myprogram.c
02

代码级优化技巧

内联函数优化

内联函数是一种重要的优化手段,可以减少函数调用的开销。使用inline关键字可以提示编译器将函数体直接嵌入到调用处:

inline int add(int a, int b) {
    return a + b;
}

但是需要注意以下限制:

  • 含有可变参数的函数不能内联
  • 包含非局部跳转(如longjmp)的函数不能内联
  • 递归函数默认不会内联
  • 函数定义前的调用不会被内联

可以通过-Winline选项检查未内联的函数:

gcc -O2 -Winline -o myprogram myprogram.c

内置函数优化

GCC提供了许多内置函数,可以用于优化特定操作。例如,__builtin_expect用于分支预测优化:

if (__builtin_expect(x == 0, 0)) {
    // 不太可能执行的代码
}

可以通过-fno-builtin选项禁用内置函数,以便进行更激进的优化:

gcc -O2 -fno-builtin -o myprogram myprogram.c

其他优化选项

  • -fomit-frame-pointer:去除帧指针,减小函数调用开销
  • -ffast-math:允许数学运算的近似优化,提高浮点运算性能
  • -finline-functions:内联小函数
  • -fstrength-reduce:优化操作强度,如将乘法替换为移位
03

链接时优化(LTO)

链接时优化(Link Time Optimization,LTO)是一种重要的全局优化技术,允许编译器在链接阶段对整个程序进行优化。LTO的基本原理是在编译阶段生成中间表示(如GIMPLE),然后在链接阶段对整个程序进行全局优化。

使用LTO的步骤如下:

  1. 编译源文件时使用-flto选项:
gcc -c -O2 -flto foo.c -o foo.o
gcc -c -O2 -flto bar.c -o bar.o
  1. 链接目标文件时同样使用-flto选项:
gcc -O2 -flto foo.o bar.o -o my_program

LTO的优势包括:

  • 跨文件的全局优化
  • 函数内联和循环优化
  • 常量传播和死代码消除

但是LTO也会增加编译时间和内存占用,因此需要根据具体场景权衡使用。

04

GCC 13新特性

GCC 13引入了一些重要的优化相关特性:

  • 移除了对某些架构的支持,如Intel MIC、cr16-elf等
  • 改进了C++标准库的启动性能,将全局iostream对象的构造移至标准库内部
  • 优化了数组边界检查,改进了-Warray-bounds选项的行为
  • 移除了对STABS调试格式的支持

这些变更有助于提升GCC的整体性能和现代化程度。

05

最佳实践

  1. 选择合适的优化级别:从-O1或-Og开始,根据性能需求逐步提升优化级别。

  2. 使用LTO进行全局优化:对于大型项目,启用LTO可以带来显著的性能提升。

  3. 谨慎使用内联:虽然内联可以减少函数调用开销,但过度使用会导致代码体积膨胀。

  4. 利用内置函数:合理使用GCC内置函数可以优化特定操作的性能。

  5. 定期检查编译器更新:新版本的GCC通常会带来更好的优化效果和新特性支持。

通过合理运用这些优化技巧,开发者可以充分发挥GCC编译器的潜力,打造出更高效、更优化的C/C++程序。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号