C 的“内联” - 对 GCC 和 Clang/LLVM 的暗示有多强?
在 C++ 中,关键字“inline”有两个用途。首先,它允许一个定义出现在多个翻译单元中。其次,它向编译器暗示函数应该内联到编译后的代码中。
我的问题:在 GCC 和 Clang/LLVM 生成的代码中,关键字“inline”是否与函数是否内联有任何关系?如果是,在什么情况下?还是完全忽略了提示?请注意,这不是一个语言问题,而是一个特定于编译器的问题。
In C++, the keyword "inline" serves two purposes. First, it allows a definition to appear in multiple translation units. Second, it's a hint to the compiler that a function should be inlined in the compiled code.
My question: in code generated by GCC and Clang/LLVM, does the keyword "inline" have any bearing on whether a function is inlined? If yes, in what situations? Or is the hint completely ignored? Note this is a not a language question, it is a compiler-specific question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
[警告:不是 C++/GCC 专家] 您需要阅读 在此处内联。
此外,这个适用于 GCC/C99。
因此,除非使用您的编译器设置(例如
-fno-inline
或-O0
),否则编译器会接受提示。我无法评论 Clang/LLVM(或者实际上是 GCC)。如果这不是一个代码高尔夫问题并且您需要知道发生了什么,我建议使用
-Winline
。[Caveat: not a C++/GCC guru] You'll want to read up on inline here.
Also, this, for GCC/C99.
So it appears that unless your compiler settings (like
-fno-inline
or-O0
) are used, the compiler takes the hint. I can't comment on Clang/LLVM (or GCC really).'I recommend using
-Winline
if this isn't a code-golf question and you need to know what's going on.通过阅读 GCC 和 LLVM 项目的代码可以收集到很多关于这方面的信息。这是通过直接阅读代码收集的一些信息。 (注意:这不一定是完全全面的,并且没有列出
inline
在每个细节中影响内联的每一种方式,它只是给出其中大部分的概述)收集的信息来自 GCC 和 LLVM 截至 2021/11/13 的当前开发 HEAD,因此将来可能不是最新的。
在GCC方面:
-finline-small-functions
(由-O2
隐含)和-finline-functions 都不是时,未声明
(由inline
进行早期内联-O2
隐含)指定inline
的函数的“坏度”值将除以 8,这样它们更有可能首先被内联内联
且未指定 -finline-small-functions(由 -O2 隐含),GCC 将不会拆分函数-finline-functions
(包含在-O2
中),GCC 通常不会研究内联非inline
函数,除非它们非常重要。短,在这种情况下它只需要-finline-short-functions
(包含在-O2
中)在LLVM方面:
inline
的函数将通过 Clang 将inlinehint
属性附加到 LLVM 字节码函数
值,默认值为 325,否则它将使用其他值(例如调用点是热还是冷以及其他类似的值)< /a> 和 如果没有否则,将使用inlinehint
函数的 inlinehint-thresholdinlinedefault-threshold
值,默认值为 225。该值与 LLVM 计算的启发式进行比较,LLVM 将为每个函数调用计算内联给定函数的成本,如果该值小于阈值,则该函数将被内联,这意味着 inlinehint 本质上会减少内联的成本。内联函数的成本约为 1.44,如 LLVM换句话说,这看起来在 GCC 和 Clang 上都是相当强烈的提示。
A lot of information can be gathered on this by reading GCC and the LLVM project's code. Here is some information that has been gathered by reading the code directly. (Note: this is not necessarily fully comprehensive and this doesn't list every single way in which
inline
affects inlining in every single detail, it's only to give an overview of most of it)This information was gathered from GCC and and LLVM's current development HEAD as of 2021/11/13, so it might not be up to date in the future.
On GCC's side:
inline
for early-inlining when neither-finline-small-functions
(implied by-O2
) and-finline-functions
(implied by-O2
) are specifiedinline
when trying to inline a function optimized for size when the caller isn't and inlining wouldn't shrink the callerinline
to be slightly better unless they are also under the inline function instructions threshold (i.e.max-inline-insns-auto
, which is explained later) (the code is complicated so I'm being kind of vague here about what exactly it does)inline
will have their "badness" value divided by 8, such that they will be much more likely to be inlined firstmax-inline-insns-auto
in many more cases when the function is not declared inline (although I can see cases where this isn't the case, such as when GCC's heuristics consider that the "speedup seems big", for example): this value is by default 15, whereas themax-inline-insns-single
value is used when inline is specified, and has a default value of 70, which implies that a function declared inline can be inlined when it is up to 4.6 times bigger than GCC would consider for a function not declared inline (note: the previous hyperlink is only the most important example of those limits being used, they are applied in some other places too)inline
and -finline-small-functions is not specified (implied by -O2)inline
functions at all without-finline-functions
(included in-O2
), unless they are very short, in which case it only just requires-finline-short-functions
(included in-O2
)On LLVM's side:
inline
will have theinlinehint
attribute attached to the LLVM bytecode function by Clanginlinehint-threshold
value forinlinehint
functions, which has a default of 325, whereas otherwise it would use other things (such as whether the callsite is hot or cold and other things like that), and if nothing else is found, will use theinlinedefault-threshold
value, which has a default of 225. This value is compared to a heuristic calculated by LLVM which will calculate for each function call how expensive inlining a given function would be, and if this value is smaller than the threshold, the function will be inlined, which means that inlinehint will essentially diminish the cost of inlining a function by ~1.44 as seen by LLVMIn other words, it looks like this is quite the strong hint, on both GCC and Clang.
来自gcc:内联函数与宏一样快的有趣解释:
An interesting explanation from gcc: An Inline Function is As Fast As a Macro:
提示的强度完全取决于您使用的编译选项。大多数编译器都可以选择不进行内联,仅内联那些标记为“内联”的内容,或者使用其最佳判断并忽略提示。
最后一个可能效果最好。 :-)
How strong the hint is depends entirely on the compile options you use. Most compilers have options to do no inlining, only inline those marked 'inline', or use its best judgement and ignore the hints.
The last one probably works best. :-)