GCC中的早班班轮和IPA班轮赛有什么区别?

时间:2018-07-16 21:02:55

标签: gcc compiler-optimization inlining

通读GCC代码注释和在线文档,似乎有两种类型的内衬-早期内衬和IPA内衬。 例如,在gcc / ipa-fnsummary.c

  

/ *在对IPA内衬进行优化和分析时,请初始化循环   优化器,以便我们可以产生适当的内联提示。

     

在优化和分析早期内衬时,请初始化节点   参数,因此我们可以产生正确的BB谓词。 * /

这两种内衬是什么?两者之间有什么区别?

2 个答案:

答案 0 :(得分:2)

简单地说:

  • 在编译单个文件时,早期的liner在单个源文件级别上运行。它将内联函数仅在已编译的源文件及其包括的头文件的范围内(单个编译单元的范围)。

  • 在整个程序优化过程中,IPA内联器在链接时间上运行。它在激活-flto选项(代表链接时间)时发生 优化。

指定-flto时,gcc将称为GIMPLE树的中间程序表示形式嵌入到每个目标文件的专用部分中。稍后,链接时间优化器(GCC的lto1可执行文件)读取此信息,并执行不同的优化过程,包括IPA内联代码,以生成最终的优化可执行文件。

两个内衬的影响可以用一个简单的例子来说明:

// foo.h
void foo() {}

// goo.h
int goo();

// goo.cpp
#include "goo.h"
int goo() { return 0x123; }

// foo.cpp
#include "foo.h"
#include "goo.h"

int main()
{
    foo();
    return goo();
}

首先,通常进行-O3编译:

g++ -O3 foo.cpp goo.cpp

通过拆卸a.outobjdump a.out -d),我们得到了main的以下代码:

00000000000004f0 <main>:
 4f0:   e9 0b 01 00 00          jmpq   600 <_Z3goov>
 4f5:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 4fc:   00 00 00 
 4ff:   90                      nop

foo()的调用已经消失了-这是早期内线的工作。但是,goo()函数foo.cpp在编译期间-flto对编译器不可见,因此无法对其进行优化。

现在,使用g++ -O3 -flto foo.cpp goo.cpp重复编译:

00000000000004f0 <main>: 4f0: b8 23 01 00 00 mov $0x123,%eax 4f5: c3 retq 4f6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 4fd: 00 00 00

我们将得到以下反汇编:

goo

这一次,对0x123的调用被内联,并被其结果assert.equal(result, group[0] != "sam1"); 取代-这是IPA内联的工作。

答案 1 :(得分:1)

根据ipa-inline.c中的内部文档,早期内联是一个简单的本地内联传递,它仅基于本地属性对当前函数中的被调用者进行内联。此过程的主要优势在于它能够删除大多数C ++代码中存在的抽象损失,并为更高级的过程间分析(IPA)准备代码。

基于IPA期间收集的信息,IPA内衬是一种更高级的内衬。由于它具有更多信息,因此可以更好地估计哪些被调用者最有利于内联。它还会修剪调用图并删除所有内联所有调用站点的功能。

有关更多信息,请参阅ipa-inline.c的内部文档