R..*_*R.. 12 c x86 gcc code-generation
我最近遇到了很多函数,其中gcc在x86上生成了非常糟糕的代码.他们都符合以下模式:
if (some_condition) {
/* do something really simple and return */
} else {
/* something complex that needs lots of registers */
}
Run Code Online (Sandbox Code Playgroud)
将简单的情况看作是一个非常小的东西,一半或更多的工作花在推动和弹出不会被修改的寄存器上.如果我手动编写asm,我会在复杂的情况下保存并恢复已保存的跨调用寄存器,并且在简单的情况下完全避免触及堆栈指针.
有没有什么方法可以让gcc变得更聪明并且自己做到这一点?最好使用命令行选项,而不是源代码中的丑陋黑客...
编辑:为了使它具体化,这里有一些非常接近我正在处理的一些函数:
if (buf->pos < buf->end) {
return *buf->pos++;
} else {
/* fill buffer */
}
Run Code Online (Sandbox Code Playgroud)
另一个:
if (!initialized) {
/* complex initialization procedure */
}
return &initialized_object;
Run Code Online (Sandbox Code Playgroud)
另一个:
if (mutex->type == SIMPLE) {
return atomic_swap(&mutex->lock, 1);
} else {
/* deal with ownership, etc. */
}
Run Code Online (Sandbox Code Playgroud)
编辑2:我应该首先提到:这些函数不能内联.他们有外部联系,他们是图书馆代码.允许它们在应用程序中内联将导致各种问题.
也许升级你的 gcc 版本?4.6 刚刚发布。据我了解,它有“部分内联”的可能性。也就是说,函数的易于集成的外部部分被内联,而昂贵的部分被转换为调用。但我必须承认我自己还没有尝试过。
编辑:我在变更日志中提到的声明:
现在支持部分内联,并且默认在 -O2 及更高版本下启用。该功能可以通过 -fpartial-inlined 进行控制。
部分内联通过短的热路径返回来分割函数。这允许更积极地内联热路径,从而获得更好的性能,并且通常可以减少代码大小(因为函数的冷部分不会重复)。
...
优化大小时的内联(在程序的冷区域或使用 -Os 编译时)已得到改进,可以更好地处理具有较大抽象损失的 C++ 程序,从而使代码更小、更快。