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

时间:2011-10-06 08:29:28

标签: c++ compiler-construction

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

这类事物是公共知识吗?

4 个答案:

答案 0 :(得分:6)

我给出了更全面的答案in this other question

基本上编译器根据成本分析得出heurstics,引用自己(这是否意味着我会老死?)

  

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

     
      
  • 您可以避免函数调用(所有寄存器保存/帧调整)
  •   
  • 你向优化器暴露了更多的上下文(死存储,死代码,常见的子表达式elimintation ......)
  •   
  • 代价是复制代码(膨胀指令缓存和可执行文件大小等)
  •   

当然,还有部分内联,其中只有部分功能是内联的,通常是if的前导foo(T* t) { if (!t) { return; } <many many things> }。{/ p>

答案 1 :(得分:3)

是的,这种信息是公共知识。特别是因为那里有大量的开源编译器。

我认为要阅读的书是Dragon Book。他们在那里经历了所有这些,不是吗?

但基本上:函数调用有成本 - 设置寄存器,跳转,收集结果。这可以循环计算。功能体还具有以周期测量的成本。比较两者。考虑缓存局部性的额外点。

答案 2 :(得分:1)

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

如果仅从一个地方调用该功能,则内联它可以减少一些指令和周期,从而改善尺寸和速度。

如果它是一个很小的功能,内联也可以这样做。

如果多次以紧密循环方式调用该函数,则内联可以提高性能。

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

编译器尝试做出最佳选择,但他们还必须考虑可配置优化选项(程序员可能会说他更喜欢速度超过大小或相反)以及需要花费多少时间。做出这些决定并生成代码(您不希望编译器大量优化所有内容,并且需要花费额外的时间或数天来编译代码)。有权衡。

此外,编译器并不是万能的。他们只是不能把某些两个和两个人放在一起,不是因为那是昂贵的,而是因为它几乎是不可能的。这就是为什么我们进行性能和负载测试,拥有分析器并让人类编写代码,因为人类通常仍然比他们的程序更聪明。

答案 3 :(得分:1)

启发式方法取决于您传递编译器的选项,以及 也取决于编译器。没有一般的答案。最 今天的编译器有他们将内联的选项组合 没有。大多数还有一些选项组合,它们内联 将取决于程序早期运行的分析器输出。 否则:从实施质量的角度来看,它是 合理地期望编译器内联函数声明inline 比未宣布inline的人更积极。它通常会 只有当激活最激进的优化时才会这样做 他们将内联一个函数,其定义不存在于 翻译单位。最后,函数中的某些内容可能会受到抑制 内联:有些编译器可能没有内联递归函数 例子(尽管g ++确实如此,至少在某些情况下)。