C++ LTO在使用GCC编译但使用LLVM LLD链接时有效吗?
我最近发现了LLVM的链接器,C++ LTO在使用GCC编译但使用LLVM LLD链接时有效吗?,c++,gcc,linker,llvm,lld,C++,Gcc,Linker,Llvm,Lld,我最近发现了LLVM的链接器,lld,它因链接速度非常快而受到赞扬。事实上,我对它进行了测试,结果非常棒,与gold相比,我的链接时间大大缩短 然而,当谈到链路时间优化时,我的知识是有限的。据我在互联网上阅读的资料所知,目标文件中产生了一些额外的代码,表示一些内部编译器结构,然后在链接阶段使用这些结构。因此,我关心的是,链接时间优化(及其好处)是否会受到这种编译器/链接器组合的影响。我希望你能解释一下这件事 我使用了gccversion9.2.0和lldversion10.0.0 用于生成对象文
lld
,它因链接速度非常快而受到赞扬。事实上,我对它进行了测试,结果非常棒,与gold
相比,我的链接时间大大缩短
然而,当谈到链路时间优化时,我的知识是有限的。据我在互联网上阅读的资料所知,目标文件中产生了一些额外的代码,表示一些内部编译器结构,然后在链接阶段使用这些结构。因此,我关心的是,链接时间优化(及其好处)是否会受到这种编译器/链接器组合的影响。我希望你能解释一下这件事
我使用了gcc
version9.2.0
和lld
version10.0.0
用于生成对象文件的命令:
/opt/gcc/9.2.0/bin/c++-fPIE-flto-ffat lto对象-fuse链接器插件-m64-O3-g-DNDEBUG-o my_object.cpp.o-c my_source_file.cpp
链接:
#-保险丝ld=gold
/opt/gcc/9.2.0/bin/c++-fPIE-flto-ffat lto对象-fuse链接器插件-m64-pie-fuse ld=gold-Wl,-z,relro-Wl,-z,now-Wl,--根据需要-静态libstdc++-静态libgcc-Wl,--线程-Wl,--线程计数,1
#-保险丝ld=lld
/opt/gcc/9.2.0/bin/c++-fPIE-flto-ffat lto对象-fuse链接器插件-m64-pie-fuse ld=lld-Wl,-z,relro-Wl,-z,now-Wl,--根据需要-static libstdc++-static libgcc-Wl,--threads-Wl,
我做了一些研究,最后得出结论,如果我们在使用gcc
编译时使用lld
,就不会进行LTO。我所做的:
基于这种有点模糊的表示:,我发现链接器并不是直接进行优化,而是在读取所有对象文件中的所有符号后,他将信息传递给lto包装器
,然后该包装器通过一些其他过程进行优化。所以我用一个hello world
cpp文件做了一个测试,用-v
标志编译它,我确实看到了前面提到的连续调用(collect2
(linker)->lto包装器
->lto1
)。但当使用默认链接器或gold
链接器时,会出现这种情况。当我使用-fuse ld=lld
标志时,只调用collect2
进程。这第一件事让我相信LTO根本就没有完成
但是,嘿,可能是lld
链接器将LTO进程内部化了,这样就不用调用任何其他进程了。所以我做了另一个测试,看看LTO是否完成(基于文章)。基本上,从一个cpp文件中,我调用了10万次在另一个cpp文件中定义的函数,一个什么都不做的函数。使用basic-O2
优化,生成的二进制运行时间约为200毫秒,因为编译器无法优化无用的函数调用。同时使用-flto
标志和ld
或gold
链接器时,生成的二进制文件在~2 ms内运行。但使用lld
链接器时,生成的二进制文件也在~200 ms内运行。因此,带lto的lld
运行速度与不带lto的lld
运行速度一样慢。没有任何优化迹象。这里要提到的是,如果不使用
-ffat lto objects
编译对象,则使用lld
链接器时,link命令将失败。此标志使对象文件变大,因为编译器不仅转储lto代码,而且转储可以在没有lto的情况下链接的代码
因此,考虑到与
lld
链接的二进制文件的时间性能,以及需要使用-ffat lto objects
编译对象这一事实,我得出结论,当使用lld
链接器时,根本无法实现lto,但是lld
使用编译器生成的非LTO代码来链接二进制文件。得出了相同的结论。lld不做lto。测试gcc8和lld 10。此外,如果使用-flto选项编译,链接器总是抱怨main未定义,也必须使用-ffat lto对象。即使使用-flto partition=none
,这是否有效?