我正在尝试整理一个嵌入式项目,其中开发人员可以选择将所有h和c文件包含在ac文件中,然后他们可以使用-whole-program选项编译一个文件以获得良好的大小优化
我讨厌这个,并决心将它变成一个传统的程序,只是使用LTO来实现同样的目标。
开发工具包中包含的版本是; aps-gcc(GCC)4.7.3 20130524(Cortus) GNU ld(GNU Binutils)2.22
使用一个.o文件.text是0x1c7ac,分成67个.o文件.text出现为0x2f73c,我添加了LTO的东西并将其缩小为0x20a44,好但远远不够。
我尝试了-gc-sections并使用了链接器插件选项,但它们没有进一步改进。
任何建议,我是否看到了LTO的正确改进?
答案 0 :(得分:0)
要使LTO完美地工作,您需要在链接阶段获得与编译阶段相同的信息和优化算法。 GNU工具无法做到这一点,我相信这实际上是创建LLVM / Clang的激励因素之一。
如果您想要检查细节上的差异,我建议您为每个选项生成一个地图文件(ld
选项-Map <filename>
),并查看是否有某些功能可以避开&#39;内嵌或更大的功能。通过将函数的定义移动到头文件并将其定义为extern inline
并将其有效地转换为宏(这是GNU扩展),可以通过强制这些函数内联来手动解决内联的缺失。
较大的功能可能不会不断传播,我不认为你可以做些什么。您可以通过仔细声明const
,leaf
,noreturn
,pure
和returns_nonnull
等功能属性来进行一些改进。这些有效地承诺,如果使用单个编译单元,该函数将以编译器可能以其他方式检测的特定方式运行,并允许其他优化。
相比之下,Clang可以将您的目标代码编译为一种特殊的字节码(LLVM代表低级虚拟机,就像JVM是Java虚拟机,并运行字节码),然后可以在链接时执行此字节码的优化(或者确实是运行时,这很酷)。由于这个字节码是优化的,无论你是否进行LTO,并且优化算法在编译器和链接器之间是通用的,理论上,无论你是否使用LTO,Clang / LLVM都应该给出完全相同的结果。
不幸的是,现在已经从LLVM中删除了C后端,我不知道如何使用LLVM LTO功能来定制您要定制的自定义CPU。
答案 1 :(得分:0)
在我看来,以前的开发人员选择的方法是正确的。这种方法为编译器提供了最多的信息,因此也是进行所需优化的最佳机会。这是一种糟糕的编译方式(任何更改都需要编译整个项目),所以将此标记为一个选项是个好主意。
当然,您必须针对此类构建运行所有集成测试,但这应该是微不足道的。除了编译时间之外,所选方法的缺点是什么(这不应该是一个问题,因为你不需要一直以这种方式构建......仅用于集成测试)。