gpt4 book ai didi

c - 编译器(通过链接时优化)如何处理快速返回的函数(提前退出路径)?

转载 作者:太空狗 更新时间:2023-10-29 17:25:35 26 4
gpt4 key购买 nike

在 C 中,如果我有一个看起来像这样的函数调用

// main.c
...
do_work_on_object(object, arg1, arg2);
...

// object.c
void do_work_on_object(struct object_t *object, int arg1, int arg2)
{
if(object == NULL)
{
return;
}
// do lots of work
}

然后编译器会在 main.o 中生成很多东西来保存状态、传递参数(在这种情况下希望在寄存器中)和恢复状态。

但是,在链接时可以观察到arg1和arg2没有用在快速返回路径中,所以清理和状态恢复可以被短路。链接器是否倾向于自动执行此类操作,还是需要打开链接时优化 (LTO) 才能使此类操作正常工作?

(是的,我可以检查反汇编代码,但我对编译器和链接器的一般行为以及在多种体系结构上的行为很感兴趣,因此希望学习其他人的经验。)

假设分析显示此函数调用值得优化,我们是否应该期望以下代码明显更快(例如,无需使用 LTO)?

// main.c
...
if(object != NULL)
{
do_work_on_object(object, arg1, arg2);
}
...

// object.c
void do_work_on_object(struct object_t *object, int arg1, int arg2)
{
assert(object != NULL) // generates no code in release build
// do lots of work
}

最佳答案

一些编译器(如 GCC 和 clang)能够进行“shrink-wrap”优化以延迟保存调用保留的 regs 直到可能的提前退出之后,如果它们能够发现模式。但有些人没有,例如apparently MSVC 16.11 still doesn't .

我不认为任何部分内联只是提前检查调用者,以避免 arg 传递和调用/ret 本身的开销。


由于编译器/链接器对此的支持不是通用的,并且即使对于收缩包装也不一定总是成功,因此您可以以将函数的逻辑分成两部分为代价的方式编写代码以获得大部分好处地点。

如果您的快速路径几乎不需要任何代码,但发生的频率足够高,请将该部分放在 header 中以便内联,然后回退到调用其余部分函数(您将其设为私有(private),因此它可以假定内联部分中的任何检查都已完成)。

例如当 galois16 因子为零时,par2 处理数据 block 的例程有一条快速路径。 (dst[i] += 0 * src[i] 是空操作,即使 * 是 Galois16 中的乘法,而 += 是 GF16 加法(即按位异或))。

注意如何 the commit in question将旧函数重命名为 InternalProcess , 并添加一个新的 template<class g> inline bool ReedSolomon<g>::Process检查快速路径,否则调用 InternalProcess . (以及进行一堆不相关的空白更改,以及一些 ifdefs ... 它最初是 2006 年的 CVS 提交。)

提交中的评论声称整体修复速度提高了 8%。

关于c - 编译器(通过链接时优化)如何处理快速返回的函数(提前退出路径)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29706147/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com