c++ - 编译器使用哪些真正的规则集来决定是否内联函数?

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

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

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

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

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

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

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

在不实际尝试和重新编译所有代码并仔 segmentation 析发出的代码的情况下,我如何估计这一点?每次我读到inline时,都会有这样一句话:编译器决定是否内联该函数。

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

最佳答案

GCC 有一组相当大的选项,可以公开其流程的工作原理,记录在 here 中。这当然不准确,因为它会随着时间的推移而调整,并且它依赖于 CPU。

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

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

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

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

关于c++ - 编译器使用哪些真正的规则集来决定是否内联函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4954752/

相关文章:

c++ - 如何让叮当警告非常简单的缩小

c++ - 显示正交的 OpenGL 投影矩阵

c++ - 信号量上的 WaitForSingleObject 不等待,立即返回

c++ - C++ 项目中的两个 main() 无法构建

c++ - 如何在 MSVC 中使用 ECPG

linux - 为什么 perf 不报告缓存未命中?

c++ - 如果资源获取可能失败,如何实现 RAII

c++ - 编译器的健壮性……天真

optimization - 梯度下降和梯度上升有什么区别?

c - 检测哪个字母最常见的程序