消除GOT寄存器的冗余负载?

时间:2011-02-22 07:16:18

标签: c optimization gcc pic

我正在处理一些代码,这些代码在编译为PIC(位置无关代码)时会慢70-80%,并且正在寻找缓解问题的方法。问题的一个重要部分是gcc坚持在每个函数中插入以下内容:

call __i686.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_,%ebx

即使最终成为该功能内容的20%。现在,ebx是一个保留调用的寄存器,相关翻译单元(源文件)中的每个函数都在加载GOT的地址,并且很容易检测到{无法从翻译单元外部调用{1}}函数(它们的地址永远不会被占用)。那么为什么gcc只能在大型外部链接函数的开头加载static一次,并生成静态链接函数,以便它们假定ebx已经加载了地址的拿到?是否有任何优化标志可以用来迫使gcc进行这种明显的大规模优化,而不是将内联限制转为天价,以便所有内容都被内联到外部函数中?

2 个答案:

答案 0 :(得分:2)

可能没有通用的治疗方法,但您可以尝试使用内联选项。我猜测编译单元中的static函数没有太多的调用者,因此代码复制的开销也不会太差。

使用gcc强制执行此类操作的最简单方法是设置attribute((always_inline))。您可以使用gcc相关宏来确保可移植性。

如果您不想修改代码(但无论如何static inline都不错),您可以使用-finline-limit选项对其进行微调。

答案 1 :(得分:1)

不是真正的解决方案,但是:如果有问题的函数没有引用文件范围变量,您可以将它们全部放在一个翻译单元中,并在没有-fPIC标志的情况下编译它们。然后像往常一样将它们与最终SO中的其他文件链接在一起。