Seb*_*ebi 7 c++ linker gcc llvm lld
我最近发现了 LLVM 的链接器,lld它因链接速度非常快而受到称赞。事实上,我测试了它,结果非常棒,与gold.
然而,当谈到链接时优化时,我的知识是有限的。据我通过阅读互联网上的内容了解到,目标文件中产生了一些额外的代码,代表一些内部编译器结构,然后在链接阶段使用。因此,我担心链接时优化(及其好处)是否受到此编译器/链接器组合的影响。我希望对此事有一些解释!
我使用了gcc版本9.2.0和lld版本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
Run Code Online (Sandbox Code Playgroud)
对于链接:
#-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,
Run Code Online (Sandbox Code Playgroud)
我做了一些研究,最后自己得出的结论是,如果我们lld在编译时使用gcc. 我做了什么:
基于这个有点模糊的演示:https://www.slideshare.net/chimerawang/gcc-lto,我发现链接器并没有直接进行优化,而是在读取所有目标文件中的所有符号后,他将信息传递给负责lto-wrapper人,然后通过其他一些流程进行优化。因此,我使用 cpp 文件进行了测试hello-world,使用标志对其进行编译-v,实际上我看到了前面提到的连续调用(collect2(linker) -> lto-wrapper-> lto1)。但这是在使用默认链接器或gold链接器时发生的。当我使用该-fuse-ld=lld标志时,仅collect2调用该进程。这第一件事让我相信 LTO 根本没有完成。
但是,嘿,也许lld链接器内部化了 LTO 进程,因此它是在不调用任何其他进程的情况下完成的。所以我又做了一次测试,看看LTO是否完成(基于这篇文章)。基本上,在一个 cpp 文件中,我调用了其他 cpp 文件中定义的函数 100 000 000 次,该函数什么也不做。使用基本-O2优化,生成的二进制文件运行时间约为 200 毫秒,因为编译器无法优化无用的函数调用。当同时使用-flto标志和ld链接器时gold,生成的二进制文件运行时间约为 2 毫秒。但是当使用lld链接器时,生成的二进制文件的运行时间也约为 200 毫秒。因此lld,使用 lto 时的运行速度与不使用 lto 时一样慢lld。没有任何优化的迹象。
这里要提到的是,使用lld链接器时,如果不使用 . 编译对象,则链接命令将会失败-ffat-lto-objects。此标志使目标文件更大,因为编译器不仅转储 lto 代码,而且转储无需 lto 即可链接的代码。
因此,考虑到 链接的二进制文件的时间性能lld以及需要使用 编译对象的事实-ffat-lto-objects,我得出的结论是,当lld使用链接器时,根本没有实现 LTO,而是lld使用编译器生成的非 LTO 代码为了链接二进制文件。