我最近遇到了很多函数,其中 gcc 在 x86 上生成了非常糟糕的代码。它们都符合以下模式:
if (some_condition) {
/* do something really simple and return */
} else {
/* something complex that needs lots of registers */
}
将简单的情况想象成非常小的事情,以至于一半或更多的工作都花在压入和弹出根本不会被修改的寄存器上。如果我手动编写 asm,我会在复杂情况下保存和恢复保存的跨调用寄存器,并在简单情况下完全避免接触堆栈指针。
有没有什么方法可以让 gcc 变得更聪明一点,并自己做这件事?最好使用命令行选项而不是源代码中的丑陋黑客...
编辑:为了使其具体化,这里有一些非常接近我正在处理的一些功能的内容:
if (buf->pos < buf->end) {
return *buf->pos++;
} else {
/* fill buffer */
}
还有一个:
if (!initialized) {
/* complex initialization procedure */
}
return &initialized_object;
还有一个:
if (mutex->type == SIMPLE) {
return atomic_swap(&mutex->lock, 1);
} else {
/* deal with ownership, etc. */
}
编辑 2: 我应该在一开始就提到:这些函数不能内联。它们具有外部链接并且它们是库代码。允许它们在应用程序中内联会导致各种问题。
最佳答案
更新
要在 gcc 中明确禁止单个函数的内联,请使用:
void foo() __attribute__ ((noinline))
{
...
}
另见 How can I tell gcc not to inline a function?
像这样的函数将定期自动内联,除非编译 -O0(禁用优化)。
在 C++ 中,您可以使用 inline 关键字提示编译器
如果编译器不接受您的提示,您可能在函数内使用了太多的寄存器/分支。通过将“复杂” block 提取到它自己的函数中,几乎可以肯定地解决了这种情况。
更新 我注意到您添加了它们是外部符号这一事实。 (请使用该关键信息更新问题)。好吧,从某种意义上说,有了外部函数,所有的赌注都没有了。我真的不敢相信 gcc 会根据定义将所有复杂函数内联到一个微小的调用程序中简单地 因为它只从那里调用。也许您可以提供一些示例代码来演示该行为,我们可以找到适当的优化标志来解决这个问题?
另外,这是C还是C++?在 C++ 中,我知道内联包含琐碎的决策函数是很常见的地方(主要是作为类声明中定义的成员)。这不会像简单的(外部)C 函数那样产生链接冲突。
您还可以定义模板函数,这些函数将在所有编译模块中完美内联,而不会导致链接冲突。
我希望您使用的是 C++,因为它会在这里为您提供大量选择。
关于c - 避免 gcc 函数序言开销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5477673/