我有一些关于GCC中LTO的新手问题,恕我直言,在互联网上很难找到我问题的答案。请考虑下图中的真实的用例(不是很专业,但对本主题来说应该足够有意义)。
在这个例子中有四个不同的库,为了这个例子的目的,我们假设每个模块都用合适的lto标志编译(这同样适用于链接器)。
inner.a
-由两个模块组成的静态库outer1.a
-静态库,由一个模块沿着嵌入其中的inner.a
库组成outer2.a
-由两个类似于inner.a
的模块组成的静态库shared.so
-分别包含outer1.a
和outer2.a
的共享库
1.某些链接到shared.so
的可执行文件
LTO机制在哪些方面可以进行优化,哪些方面不能?据我所知:
inner.a
应该得到优化-它是一个静态库outer1.a
也是一样-链接器具有module3.o
和要嵌入的inner.a
库的完整视图outer2.a
与上述库类似
那么shared.so
呢?它是一个共享对象,但是由两个静态库组成,为了在outer1.a
和outer2.a
链接期间进行优化,仍然应该保留完整视图。
标记为黄框的可执行文件与shared.so
动态链接,因此LTO机制实际上什么也不能做,“幸运链”在那里被打破了?
我也非常感谢任何关于这个特定主题的材料。
1条答案
按热度按时间czfnxgou1#
据我了解:
inner.a
应该得到优化-它是一个静态库你似乎有一个不正确的链接思维模式。
inner.a
只是.o
文件的容器。在静态链接时,单个.o
文件会被复制(类似于从书架上取下一本书),并 * 链接 * 到一个可执行文件或共享库中。在 * 那个 * 阶段,LTO可能会发生。那么
shared.so
呢?它是一个共享对象,但是由两个静态这又是一个"错误"。
shared.so
(可能)包含来自(复制自)各种.o
的"代码"和"数据",但它不包含这些对象,当然也不包含任何归档库。现在我们来讨论LTO,假设
module1.c
包含以下代码:module5.c
的表达式是:编译
module1.c
时,编译器无法将该代码转换为因为它不知道
foo()
返回什么。但是,当LTO过程在链接
shared.so
时运行时,该过程 * 不 * 知道foo()
返回常数值,并且因此可以优化bar()
以 * 也 * 返回常数。标记为黄框的可执行文件与
shared.so
动态链接,因此LTO机制实际上什么也不能做正确。
另外,一个归档库不能像图片所示的那样包含另一个归档库。你可以把
inner.a
放到outer.a
中,但是如果你这样做了,链接器会忽略inner.a
,而把outer.a
当作它只包含module3.o
。