Understanding Compiler Optimization in LLVM

https://www.bilibili.com/video/BV1yE411y7Ac https://www.youtube.com/watch?v=FnGCDLhaxKU

https://meetingcpp.com/files/mcpp/2015/talks/meetingcxx_2015-understanding_compiler_optimization_themed_copy.pdf

google llvm组大佬chandler carruth, 主要讲解了现代编译器(以LLVM为例)哪些优化方面的工作是最重要的,以及说对于使用者与优化编译器交互时候需要知道哪些事情。

编译器优化整体上划分为3个工作:

  1. cleanup 把不需要的分支跳转以及load/store去除掉
  2. canonicalization 归一化,让意图相同但是实现不同的C++代码被翻译成相同的IR格式
  3. collapse abstractions. 对抽象进行折叠压缩。我的理解就是整个程序看起来像是许多抽象片段,优化编译器要将这些片段整合压缩在一起,达到最佳性能。

优化编译器最关键的几个抽象就是:

  1. inline function call
  2. memory loads & stores (先转换为读写寄存器,然后在寄存器分配阶段优化)
  3. loops (loop prehead + exit两个block, 以及使用向量化做优化)

而过去编译原理书籍里面说的常量折叠或者是传播,在SSA下面变得非常简单,在现代编译器中几乎就不是问题。SSA里面明确了程序的控制流以及数据流,让许多之前很复杂的优化变得十分简单。

将函数调用这个抽象折叠起来几乎是现代编译器中最重要的单项优化,talk中提到了(bottom-up scc-based call graph) 这个方法。我的理解就是,llvm需要分析每个函数之间的调用关系,一个SCC里面的函数调用可以被折叠起来作为一个内联单元存在。