Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 消除GOT寄存器的冗余负载?_C_Optimization_Gcc_Pic - Fatal编程技术网

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

C 消除GOT寄存器的冗余负载?,c,optimization,gcc,pic,C,Optimization,Gcc,Pic,我正在处理一些编译为PIC(位置独立代码)时速度慢了70-80%的代码,并正在寻找缓解问题的方法。问题的很大一部分在于gcc坚持在每个函数中插入以下内容: call __i686.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_,%ebx 即使最终占函数内容的20%。现在,ebx是一个保留调用的寄存器,相关翻译单元(源文件)中的每个函数都加载了GOT的地址,并且很容易检测到,静态函数不能从翻译单元外部调用(它们的地址永远不会被获取)。那么,为什么gcc不能

我正在处理一些编译为PIC(位置独立代码)时速度慢了70-80%的代码,并正在寻找缓解问题的方法。问题的很大一部分在于gcc坚持在每个函数中插入以下内容:

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

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

可能没有通用的解决方法,但您可以尝试使用内联选项。我想编译单元中的
静态
函数没有太多调用方,因此代码复制的开销不会太大

使用gcc强制执行这些操作的最简单方法是设置一个
属性((总是内联的))
。您可以使用依赖于gcc的宏来确保可移植性


如果您不想修改代码(但不管怎样,静态内联也好),您可以使用
-finline limit
选项对其进行微调。

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

这看起来相关且令人失望:仅仅因为函数是静态的,并不意味着它们不能作为函数指针传递给其他编译单元。我想知道,添加表是否真的会使这些函数的速度降低这么多。你真的分析过吗?如果是这样,那么这样的短函数很适合内联,这也节省了创建堆栈框架的开销。@DatenWalf:正如我在问题中所说的,它们的地址永远不会被获取,因此不能作为函数指针传递。gcc已经对永远无法从外部调用的函数进行了大量优化(如切换到pass by register)。如果它们不访问静态存储持续时间的变量,那么get寄存器将不会首先加载。问题是它们确实如此,而且必须如此。将所有全局变量打包到一个结构中并将指向该结构的指针作为函数参数传递如何?加上+1-这实际上是一个有用的想法,但不太适用于我的问题,因为函数同时处理外部和静态全局状态(前者以只读方式,后者以读写方式),当我更改所有这些小函数以向它们传递两个额外的指针时,我认为我增加的开销将与PIC寄存器加载一样糟糕。
-O3
以文件大小加倍为代价解决了这个问题。目前还没有消息表明这是否会因为缓存问题而影响某些调用方的性能……嗯,我假设您已经打开了某种级别的
-O
。如果您对
-O3
的功能不满意,您可以选择其中的一些选项。我通常使用
-Os
,这会产生更小的代码,并且性能大致相同(有时比
-O3
快10%,有时慢10%)@R。。,所以编译器按照你的要求做了,只是优化了大小而不是速度。检查通过了。这似乎是目前唯一的解决办法。允许gcc优化加载PIC寄存器的
可见性(“内部”)
文档,但
可见性
对于
静态
函数无效,而静态函数(只要它们的地址没有被取下)应该已经在与
内部
一样严格的类中。因此,这似乎只是一个gcc缺陷/限制:-(