我正在处理一些代码,这些代码在编译为PIC(位置无关代码)时会慢70-80%,并且正在寻找缓解问题的方法。问题的一个重要部分是gcc坚持在每个函数中插入以下内容:
call __i686.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
即使最终成为该功能内容的20%。现在,ebx
是一个保留调用的寄存器,相关翻译单元(源文件)中的每个函数都在加载GOT的地址,并且很容易检测到{无法从翻译单元外部调用{1}}函数(它们的地址永远不会被占用)。那么为什么gcc只能在大型外部链接函数的开头加载static
一次,并生成静态链接函数,以便它们假定ebx
已经加载了地址的拿到?是否有任何优化标志可以用来迫使gcc进行这种明显的大规模优化,而不是将内联限制转为天价,以便所有内容都被内联到外部函数中?
答案 0 :(得分:2)
可能没有通用的治疗方法,但您可以尝试使用内联选项。我猜测编译单元中的static
函数没有太多的调用者,因此代码复制的开销也不会太差。
使用gcc强制执行此类操作的最简单方法是设置attribute((always_inline))
。您可以使用gcc相关宏来确保可移植性。
如果您不想修改代码(但无论如何static inline
都不错),您可以使用-finline-limit
选项对其进行微调。
答案 1 :(得分:1)
不是真正的解决方案,但是:如果有问题的函数没有引用文件范围变量,您可以将它们全部放在一个翻译单元中,并在没有-fPIC标志的情况下编译它们。然后像往常一样将它们与最终SO中的其他文件链接在一起。