GCC中Early inliner和IPA inliner有什么区别?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GCC中Early inliner和IPA inliner有什么区别?相关的知识,希望对你有一定的参考价值。
通过GCC代码注释和在线文档阅读,似乎有两种类型的内联器 - 早期内联器和IPA内联器。例如,在gcc / ipa-fnsummary.c中
/ *在优化和分析IPA内联器时,初始化循环优化器,以便我们可以生成适当的内联提示。
在优化和分析早期内联时,初始化节点参数,以便我们可以生成正确的BB谓词。 * /
这两种内联器是什么?这两者有什么区别?
简单的说:
- 在编译单个文件时,早期内联函数在单个源文件级别上运行。它将内联在已编译源文件范围内的函数及其包含的头文件(单个编译单元的范围)。
- 在整个程序优化期间,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.out
(objdump 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
- 这是IPA内联的工作。
根据ipa-inline.c中的内部文档,早期内联是一个简单的本地内联传递,内联callees在当前函数中仅基于本地属性。这个过程的主要优势在于它能够消除大多数C ++代码中存在的抽象惩罚,并为更高级的过程间分析(IPA)准备代码。
IPA内联器是基于IPA期间收集的信息的更先进的内联器。由于它有更多的信息,它可以更好地估计哪些被调用者最有利于内联。它还将修剪呼叫图并删除所有呼叫站点已内联的功能。
有关更多信息,请参阅ipa-inline.c的内部文档
以上是关于GCC中Early inliner和IPA inliner有什么区别?的主要内容,如果未能解决你的问题,请参考以下文章