编译器如何确定是否值得使我的函数内联?

How does a compiler decide whether it's worth making my functions inline or not?

本文关键字:函数 我的 何确定 是否 值得 编译器      更新时间:2023-10-16

我想知道是否有人知道c++编译器通常用来决定是否在编译时内联函数的逻辑(假设内联已被请求)。

这类事情是公众所知的吗?

对于另一个问题,我给出了更彻底的答案。

基本上编译器有基于成本分析的启发式,引用我自己的话(这是否意味着我老了?)

如果你考虑内联及其后果,你就会意识到:

  • 你避免一个函数调用(与所有的寄存器保存/帧调整)
  • 您向优化器暴露了更多上下文(死存储,死代码,公共子表达式消除…)
  • 以重复代码为代价(增加指令缓存和可执行文件大小等)

当然,也有部分内联,其中只有部分函数是内联的,通常是if的前置守卫,如foo(T* t) { if (!t) { return; } <many many things> }

是的,这类信息是公共知识。尤其是现在市面上有大量的开源编译器。

我相信要读的书是龙书。他们把所有这些都做了一遍,不是吗?

但是基本上:函数调用是有成本的——设置寄存器,跳转,收集结果。这可以用循环来计算。函数体也有以周期衡量的成本。比较两者。考虑缓存局部性的额外加分。

我认为编译器使用某种启发式方法来决定是否内联函数。

如果函数只从一个地方调用,内联它可以节省一些指令和周期,提高大小和速度。

如果它是一个小函数,内联也可以这样做。

如果函数在紧密循环中被多次调用,内联可以提高性能。

与此同时,内联会导致整体代码更大,并且由于缓存更多代码,也可能对性能产生一些负面影响。

编译器试图做出最佳选择,但他们也必须考虑到诸如可配置优化选项(程序员可能会说他更喜欢速度而不是大小或相反)以及他们做出这些决定和生成代码所需的时间(你不希望编译器大量优化所有内容,并花费许多额外的时间来编译代码)。这是有权衡的。

同样,编译器也不是万能的。他们只是不能把某些二和二放在一起,不是因为这很贵,而是因为这几乎是不可能的。这就是为什么我们做性能和负载测试,有分析器,让人写代码,因为人类通常比他们的程序更聪明。

启发式将取决于您传递给编译器的选项,以及也取决于编译器。没有一个通用的答案。大多数现在的编译器有内联的选项组合什么都没有。大多数还具有内联选项的组合将取决于程序早期运行的分析器输出。否则:从实现质量的角度来看,它是期望编译器内联函数声明inline是合理的比未申报inline的更具攻击性。通常会的只有当最激进的优化被激活时类中没有定义的函数将被内联翻译单元。最后,某些东西在功能上可能会受到抑制内联:一些编译器可能不会内联递归函数,例如示例(尽管至少在某些情况下,g++确实如此)。