GCC -链路时间优化真正适用的地方?

x8diyxa7  于 2023-03-07  发布在  其他
关注(0)|答案(1)|浏览(149)

我有一些关于GCC中LTO的新手问题,恕我直言,在互联网上很难找到我问题的答案。请考虑下图中的真实的用例(不是很专业,但对本主题来说应该足够有意义)。
在这个例子中有四个不同的库,为了这个例子的目的,我们假设每个模块都用合适的lto标志编译(这同样适用于链接器)。

  1. inner.a-由两个模块组成的静态库
  2. outer1.a-静态库,由一个模块沿着嵌入其中的inner.a库组成
  3. outer2.a-由两个类似于inner.a的模块组成的静态库
  4. shared.so-分别包含outer1.aouter2.a的共享库
    1.某些链接到shared.so的可执行文件

LTO机制在哪些方面可以进行优化,哪些方面不能?据我所知:

  • inner.a应该得到优化-它是一个静态库
  • outer1.a也是一样-链接器具有module3.o和要嵌入的inner.a库的完整视图
  • outer2.a与上述库类似

那么shared.so呢?它是一个共享对象,但是由两个静态库组成,为了在outer1.aouter2.a链接期间进行优化,仍然应该保留完整视图。
标记为黄框的可执行文件与shared.so动态链接,因此LTO机制实际上什么也不能做,“幸运链”在那里被打破了?
我也非常感谢任何关于这个特定主题的材料。

czfnxgou

czfnxgou1#

据我了解:
inner.a应该得到优化-它是一个静态库
你似乎有一个不正确的链接思维模式。inner.a只是.o文件的容器。在静态链接时,单个.o文件会被复制(类似于从书架上取下一本书),并 * 链接 * 到一个可执行文件或共享库中。在 * 那个 * 阶段,LTO可能会发生。
那么shared.so呢?它是一个共享对象,但是由两个静态
这又是一个"错误"。shared.so(可能)包含来自(复制自)各种.o的"代码"和"数据",但它不包含这些对象,当然也不包含任何归档库。
现在我们来讨论LTO,假设module1.c包含以下代码:

extern int foo();
int bar() { return foo() + 1; }

module5.c的表达式是:

int foo() { return 42; }

编译module1.c时,编译器无法将该代码转换为

int bar() { return 43; }

因为它不知道foo()返回什么。
但是,当LTO过程在链接shared.so时运行时,该过程 * 不 * 知道foo()返回常数值,并且因此可以优化bar()以 * 也 * 返回常数。
标记为黄框的可执行文件与shared.so动态链接,因此LTO机制实际上什么也不能做
正确。
另外,一个归档库不能像图片所示的那样包含另一个归档库。你可以把inner.a放到outer.a中,但是如果你这样做了,链接器会忽略inner.a,而把outer.a当作它只包含module3.o

相关问题