自编教材实操课程分享:第五章—链接时优化
先进编译实验室
2024年04月30日 09:08
收录于文集
共28篇


本文主要介绍链接时优化。实验环境是CentOS7 + LLVM。

1、优化方法简述

链接时优化是链接期间的程序优化,多个中间文件通过链接器合并在一起组合为一个程序,缩减代码体积,并通过对整个程序的分析以实现更好的运行时性能。优化人员通过选项-flto指示LLVM编译器生成含有LLVM比特码的.o文件,将代码生成延迟到链接阶段,并在链接阶段对代码实现进一步地优化。链接时优化如下图所示。

当链接器检测到.o文件为LLVM比特码时,会将所有的比特码文件读入内存并链接起来,然后再进行跨文件地内联、常量传播和更激进地死代码消除等优化。

选项-flto后可跟参数:

(1) -flto=full指链接时优化将分散的目标文件的LLVM IR组合到一个大的LLVM目标文件中,然后对其整体分析、优化并生成机器码。

(2) -flto=thin是把目标文件分开,根据需要才从其它目标文件中导入功能,使用选项-flto=thin链接的速度要快于使用选项-flto=full。

2、 示例分析

示例包含了3个文件,分别是a.h文件、a.c文件以及main.c文件。

运行命令:

(1)clang -flto -c a.c -o a.o

(2)clang -flto -c main.c -o main.o

(3)clang -flto a.o main.o -o main

LLVM将输入的源文件a.c编译成LLVM比特码文件a.o,将输入的源文件main.c编译成本机目标代码main.o。

链接器首先识别出a.c中的foo2()是LLVM比特码文件中定义的外部可见符号,完成通常的符号解析传递,发现foo2()并没有被使用后,LLVM编译器删除foo2()。一旦删除了foo2(),编译器会识别出条件i=0,这表明foo3()从来没被使用过,因此删除foo3(),之后删除foo4()。这个例子说明了与链接器紧密集成的优点,编译器不能在没有链接器输入的情况下删除foo3()。

3、总结

在程序的编译阶段,LLVM编译器通过建立全局函数调用图从而发现并删除没有被调用的死函数。在程序的链接阶段,链接器对所有的输入文件进行解析后,可以建立所有符号及函数的相互引用关系,从而发现并删除没有被引用的符号及对应的函数。可以看出,LLVM编译器和链接器之间的紧密集成实现了更多的优化。

4、 参考资料

(1)自编教材分享:第五章—编译与运行优化(三) - 哔哩哔哩 (bilibili.com)​

(2)LLVM LTO(Link Time Optimizer) 链接时优化-CSDN博客