c++ - 使用 GCC 编译但链接 LLVM LLD 时 LTO 是否有效?

标签 c++ gcc linker llvm lld

我最近发现了 LLVM 的链接器 lld,它因非常快速的链接而受到称赞。事实上,我对其进行了测试,结果非常棒,与 gold 相比,我的案例中的链接时间大大减少了。

但是,在谈到链接时优化时,我的知识是有限的。据我通过阅读互联网上的资料了解到,目标文件中产生了一些额外的代码,代表了一些内部编译器结构,然后在链接阶段使用这些代码。因此,我担心链接时优化(及其好处)是否会受到此编译器/链接器组合的影响。我将不胜感激对此事的一些解释!

我使用的是 gcc 版本 9.2.0lld 版本 10.0.0

我用来生成目标文件的命令:

/opt/gcc/9.2.0/bin/c++ -fPIE -flto -ffat-lto-objects -fuse-linker-plugin -m64 -O3 -g -DNDEBUG -o my_object.cpp.o -c my_source_file.cpp

链接:

#-fuse-ld=gold
/opt/gcc/9.2.0/bin/c++ -fPIE -flto -ffat-lto-objects -fuse-linker-plugin -m64 -pie -fuse-ld=gold -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -static-libstdc++ -static-libgcc -Wl,--threads -Wl,--thread-count,1
#-fuse-ld=lld
/opt/gcc/9.2.0/bin/c++ -fPIE -flto -ffat-lto-objects -fuse-linker-plugin -m64 -pie -fuse-ld=lld -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -static-libstdc++ -static-libgcc -Wl,--threads -Wl,

最佳答案

我做了一些研究,最后自己得出结论,如果我们在用 gcc 编译时使用 lld,则不会完成 LTO。我做了什么:

基于这个有些模糊的介绍:https://www.slideshare.net/chimerawang/gcc-lto ,我发现链接器并没有直接进行优化,而是在读取了所有目标文件中的所有符号后,将信息传递给 lto-wrapper,然后后者通过一些其他过程。因此,我使用 hello-world cpp 文件进行了测试,并使用 -v 标志对其进行了编译,实际上我看到了前面提到的连续调用(collect2 (链接器)-> lto-wrapper -> lto1)。但这是在使用默认链接器或 gold 链接器时。当我使用 -fuse-ld=lld 标志时,只有 collect2 进程被调用。这第一件事让我相信 LTO 根本没有完成。

但是,嘿,也许 lld 链接器内化了 LTO 进程,因此无需调用任何其他进程即可完成。所以我做了另一个测试,看看 LTO 是否完成(基于 this 文章)。基本上,我从一个 cpp 文件中调用了 100 000 000 次在其他 cpp 文件中定义的函数,该函数什么都不做。使用基本的 -O2 优化,生成的二进制文件运行时间约为 200 毫秒,因为编译器无法优化无用的函数调用。当同时使用 -flto 标志和 ldgold 链接器时,生成的二进制文件运行时间约为 2 毫秒。但是当使用 lld 链接器时,生成的二进制文件也会在 ~200 毫秒内运行。所以带 lto 的 lld 运行速度和不带 lto 的 lld 一样慢。没有任何优化迹象。
在这里要提到的是,使用 lld 链接器,如果对象不使用 -ffat-lto-objects 编译,链接命令将失败。此标志使目标文件更大,因为编译器不仅转储 lto 代码,还转储无需 lto 即可链接的代码。

因此,考虑到与 lld 链接的二进制文件的时间性能以及需要使用 -ffat-lto-objects 编译对象的事实,我得出结论当使用 lld 链接器时,根本没有实现 LTO,但是 lld 使用编译器生成的非 LTO 代码来链接二进制文件。

关于c++ - 使用 GCC 编译但链接 LLVM LLD 时 LTO 是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58084395/

相关文章:

c++ - 如何以字节序不可知的方式读取 UTF-16 代码点的长度

c - 是 GCC 的选项 -O2 破坏了这个小程序还是我有未定义的行为

c++ - 尽管使用指令,gcc 11.3.0 仍找不到运算符

c++ - 如何定义一个地址为空的对象?

c++ - 使用移动语义和支撑初始化对构造函数参数进行排序?

c++ - 功能性、bind1st 和 mem_fun

c++ - 是否可以在 Windows 上静态链接 Qt::phonon?

ffmpeg - 用 cmake 链接 ffmpeg 错误

c++ - 从剪贴板获取文本后,需要将一个字符串插入另一个字符串的建议

c - C 预处理器如何知道扩展什么不扩展?