gcc LTO:限制优化范围

gcc LTO: Limit scope of optimization

相当大的共享库(许多模板实例化)的 LTO 构建需要相当长的时间(> 10 分钟)。现在我知道了一些关于这个库的事情,并且可以指定某种 "blacklist" 形式的目标文件 不需要 一起分析(因为没有它们之间的调用应该是内联的),或者我可以指定 应该 一起分析的目标文件组。这是否可能(不拆分库)?

您可以完全从 link 时间优化过程中排除对象文件,只需在没有 -flto 的情况下构建它即可。

假设您要将 a.cb.c 作为一组进行优化,将 c.cd.c 作为另一组进行优化。您可以按如下方式使用 -combine GCC 开关:

$ gcc -O3 -c -combine a.c b.c -o group1.o
$ gcc -O3 -c -combine c.c d.c -o group2.o

请注意,您不需要使用 LTO,因为 -combine 开关在优化代码之前会合并多个源代码文件。

编辑

-combine 目前仅支持 C 代码。实现此目的的另一种方法是使用 #include 指令,如下所示:

// file group1.cpp
#include "a.cpp"
#include "b.cpp"

// file group2.cpp
#include "c.cpp"
#include "d.cpp"

然后可以在不使用 LTO 的情况下编译它们,如下所示:

g++ -O3 group1.cpp group2.cpp

这有效地模拟了分组或部分 LTO。

但是,尚不清楚这种技术还是 中提出的技术编译速度更快。此外,代码可能不会以完全相同的方式进行优化。因此,应比较使用每种技术生成的代码的性能。然后可以使用首选技术。

ld 有一个 little-used 功能,称为 -r/--relocatable,可用于将多个目标文件合并为一个,稍后可以链接到最终产品。如果可以让 LTO 在这里发生,但不是以后,您可以拥有您正在寻找的那种 "partial" LTO。

遗憾的是ld -r行不通;它只是组合了所有 LTO 信息,以便稍后处理。但通过 gcc 驱动程序 (gcc -r) 调用它似乎有效:

a.c

int a() {
    return 42;
}

b.c

int a(void);

int b() {
    return a();
}

c.c

int b(void);

int c() {
    return b();
}

d.c

int c(void);

int main() {
    return c();
}
$ gcc -O3 -flto -c [a-d].c
$ gcc -O3 -r -nostdlib a.o b.o -o g1.o
$ gcc -O3 -r -nostdlib c.o d.o -o g2.o
$ gcc -O3 -fno-lto g1.o g2.o
$ objdump -d a.out
...
00000000000004f0 <main>:
 4f0:   e9 1b 01 00 00          jmpq   610 <b>
...
0000000000000610 <b>:
 610:   b8 2a 00 00 00          mov    [=14=]x2a,%eax
 615:   c3                      retq   
...

所以main()被优化为return b();b()被优化为return 42;,但是两组之间没有过程间优化。