避免 gcc 函数序言开销?

2024-05-19

我最近遇到了很多 gcc 在 x86 上生成非常糟糕的代码的函数。它们都符合以下模式:

if (some_condition) {
    /* do something really simple and return */
} else {
    /* something complex that needs lots of registers */
}

将简单情况视为非常小的事情,以至于一半或更多的工作都花在压入和弹出根本不会被修改的寄存器上。如果我手工编写汇编,我会在复杂情况下保存和恢复跨调用保存的寄存器,并在简单情况下完全避免触及堆栈指针。

有什么办法可以让 gcc 变得更聪明一点并自己做这件事吗?最好使用命令行选项,而不是源代码中的丑陋黑客......

Edit:为了具体起见,以下是与我正在处理的一些功能非常接近的内容:

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. */
}

Edit 2:我应该首先提到:这些函数不能内联。它们具有外部链接并且是库代码。允许它们内联到应用程序中会导致各种问题。


Update

要显式抑制 gcc 中单个函数的内联,请使用:

void foo() __attribute__ ((noinline))
{
  ...
}

也可以看看我如何告诉 gcc 不要内联函数? https://stackoverflow.com/questions/1474030/how-can-i-tell-gcc-not-to-inline-a-function


除非编译 -O0(禁用优化),否则此类函数将定期自动内联。

在 C++ 中,您可以使用 inline 关键字提示编译器

如果编译器不接受您的提示,您可能在函数内使用了太多寄存器/分支。通过将“复杂”块提取到它自己的函数中,几乎可以肯定可以解决这种情况。


Update我注意到您添加了它们是外部符号的事实。 (请用重要信息更新问题)。好吧,从某种意义上说,有了外部函数,所有的赌注都消失了。我真的不敢相信 gcc 根据定义会将所有复杂函数内联到一个微小的调用者中simply因为它只是从那里调用的。也许您可以提供一些示例代码来演示该行为,我们可以找到适当的优化标志来解决这个问题?

Also,这是C还是C++?在 C++ 中,我知道内联包含简单的决策函数(主要是在类声明中定义的成员)是很常见的。这不会像简单(外部)C 函数那样产生链接冲突。

您还可以定义模板函数,使其完美内联在所有编译模块中,而不会导致链接冲突。

我希望您使用 C++,因为它会给您提供大量选择。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

避免 gcc 函数序言开销? 的相关文章