【问题标题】:What are any real sets of rules compilers use to decide whether to inline a function?编译器使用哪些真正的规则集来决定是否内联函数?
【发布时间】:2011-02-10 08:16:38
【问题描述】:

我们在一个通用实用程序库中有一个用于指示错误的宏,如下所示:

#define OurMacro( condition ) \
    if( condition ) { \
    } else { \
        CallExternalFunctionThatWillThrowAnException( parametersListHere ); \
    } \

我所说的parametersListHere 是由编译器在每次宏扩展时填充的常量和宏的逗号分隔列表。

该函数调用始终解析为调用 - 函数实现不会暴露给编译器。该函数有六个参数,在调试配置中它们都有有意义的值,而在发布配置中只有两个具有有意义的值,其他的则传递相同的默认值。

通常条件会成立,所以我不关心调用有多快,我只关心代码膨胀。使用 6 个参数调用该函数需要 7 个 x86 指令(6 个 pushes 和一个 call),如果将函数签名更改为只有两个参数,显然可以避免其中的 4 个 pushes - 这可以是通过引入以这种方式实现的中间“门”函数来完成,它的实现对编译器是不可见的。

我需要估计我是否应该坚持这种改变。到目前为止,我预计的主要改进是减少参数数量将在每次调用时减少 4 条指令,这意味着围绕宏扩展的代码将变得更小,编译器将更有可能内联它并进一步优化发出的代码。

如果不实际尝试并重新编译我们所有的代码并仔细分析发出的代码,我该如何估算?每次我读到inline 时,都会有一条语句表明编译器决定是否内联函数。

我能看到一些关于函数内部如何影响编译器内联决策的确切规则吗?

【问题讨论】:

  • 有什么原因你没有#ifdef NDEBUG 开关的两个不同功能?
  • @Matthieu M.:原始函数可能已经从一些我不知道的代码中调用。无论如何,使用新函数或通过更改现有函数签名,我可以得到完全相同的结果,所以我选择哪种方式并不重要。

标签: c++ visual-c++ optimization compiler-construction inline


【解决方案1】:

GCC 有一组相当多的选项来公开他们的过程是如何工作的,记录在 here。这当然不准确,因为它会随着时间的推移进行调整并且依赖于 CPU。

第一条规则是“它们的主体小于预期的函数调用代码”。 第二条规则是“静态函数调用一次”。

还有一些参数会影响 inling 过程,例如max-inline-insns-singleinsn 是 GCC 编译器中的伪指令,在这里用作函数复杂度的度量。参数max-inline-insns-auto 的文档清楚地表明,手动声明函数inline 可能会导致考虑内联,即使它对于自动内联来说太大了。

内联不是一个全有或全无的过程,因为有一个 -fpartial-inlining 标志。

当然,您不能单独考虑内联。公共子表达式消除 (CSE) 使代码更简单。这是一个优化过程,可以使函数小到可以内联。内联后,可能会发现新的公共子表达式,因此应该再次运行 CSE 通道,这反过来可能会触发进一步的内联。 CSE 并不是唯一需要重新运行的优化。

【讨论】:

    【解决方案2】:

    关于哪些函数被内联以及在什么条件下(例如选择的优化级别)的规则是特定于每个编译器的,所以我建议您查看编译器的文档。但是,一个只转发给另一个函数的函数(如您所建议的)应该是任何支持它的编译器内联的良好候选者。

    一些编译器有一种机制,您可以通过该机制标记您确实希望内联函数,例如MSVC++ 有 __forceinline。

    【讨论】:

    • 我不建议将转发功能作为内联的候选者。我希望它被隐藏起来,这样它就不会被内联,并且调用它的代码本身会变得更小。
    • 抱歉,我误解了你想让门函数做什么。我认为它的目的是在发布模式下将 6 参数调用转发到 2 参数函数,从而达到您正在寻找的结果(即在发布版本中消除额外 4 参数的代码,前提是门函数内联)。
    • 如果门被内联,那些额外的参数传递也被内联,额外的代码又回来了。
    【解决方案3】:

    如果您使用的是 Visual C++,您可以使用__forceinline强制编译器内联函数。

    【讨论】:

      猜你喜欢
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多