C 的“内联” - 对 GCC 和 Clang/LLVM 的暗示有多强?

发布于 2024-10-20 20:37:00 字数 210 浏览 1 评论 0原文

在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

大海や 2024-10-27 20:37:00

[警告:不是 C++/GCC 专家] 您需要阅读 在此处内联

此外,这个适用于 GCC/C99。

程度
使用内联提出的建议
函数说明符有效(C99
6.7.4)。

  • 如果 -fno-inline 选项为,GCC 将不会内联任何函数
    使用或如果使用 -O0。否则,海湾合作委员会
    可能仍然无法内联
    由于多种原因而发挥作用;这
    -Winline 选项可用于确定函数是否尚未被调用
    内联,为什么不呢。

因此,除非使用您的编译器设置(例如 -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.

The extent to which
suggestions made by using the inline
function specifier are effective (C99
6.7.4).

  • GCC will not inline any functions if the -fno-inline option is
    used or if -O0 is used. Otherwise, GCC
    may still be unable to inline a
    function for many reasons; the
    -Winline option may be used to determine if a function has not been
    inlined and why not.

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.

随梦而飞# 2024-10-27 20:37:00

通过阅读 GCC 和 LLVM 项目的代码可以收集到很多关于这方面的信息。这是通过直接阅读代码收集的一些信息。 (注意:这不一定是完全全面的,并且没有列出 inline 在每个细节中影响内联的每一种方式,它只是给出其中大部分的概述)

收集的信息来自 GCC 和 LLVM 截至 2021/11/13 的当前开发 HEAD,因此将来可能不是最新的。

在GCC方面:

在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:

On LLVM's side:

In other words, it looks like this is quite the strong hint, on both GCC and Clang.

摇划花蜜的午后 2024-10-27 20:37:00

来自gcc:内联函数与宏一样快的有趣解释:

某些呼叫无法集成
各种原因(特别是,电话
位于函数定义之前
不能整合,也不能整合
内的递归调用
定义)
。如果有一个
非集成调用,则函数
被编译为汇编代码
通常。该函数还必须是
如果程序像往常一样编译
引用它的地址,因为
无法内联。

请注意函数中的某些用法
定义可能使其不适合
内联替换。其中
用法有:使用 varargs、使用
alloca,使用可变大小的数据
类型(参见可变长度),使用
计算 goto (参见标签作为值),
使用非局部 goto 和嵌套
函数(请参阅嵌套函数)。
使用 -Winline 将在以下情况时发出警告
无法标记为内联的函数
替换,并给出理由
对于失败。

根据 ISO C++ 的要求,GCC 认为
中定义的成员函数
要标记为内联的类的主体
即使它们没有明确地
使用 inline 关键字声明。你
可以用以下方法覆盖它
-fno-默认内联;请参阅控制 C++ 方言的选项。

GCC 不会内联任何函数
除非您指定,否则不会优化
的“always_inline”属性
函数,像这样:

 /* 原型。 */
 内联 void foo (const char) __attribute__((always_inline));本节的其余部分是具体的

到 GNU C90 内联。

当内联函数不是静态时,
那么编译器必须假设
可能有来自其他来源的电话
文件;因为全局符号可以是
在任何程序中只定义一次,
函数不得定义在
其他源文件,所以调用
其中无法整合。
因此,非静态内联
函数总是自行编译
以通常的方式。

如果您同时指定内联和外部
在函数定义中,则
定义仅用于内联。
在任何情况下都不会编译该函数
它自己的,即使你引用它的
明确地址。这样的地址
成为外部参考,就好像
你只声明了这个函数,
并且没有定义它。

内联和外部的结合
几乎具有宏的效果。这
使用它的方法是放置一个函数
在头文件中定义这些
关键字,并放置另一个副本
定义(缺少内联和外部)
在库文件中。中的定义
头文件将导致大多数调用
到要内联的函数。如果有的话
该功能的用途仍然存在,他们将
请参阅中的单个副本
图书馆。

An interesting explanation from gcc: An Inline Function is As Fast As a Macro:

Some calls cannot be integrated for
various reasons (in particular, calls
that precede the function's definition
cannot be integrated, and neither can
recursive calls within the
definition)
. If there is a
nonintegrated call, then the function
is compiled to assembler code as
usual. The function must also be
compiled as usual if the program
refers to its address, because that
can't be inlined.

Note that certain usages in a function
definition can make it unsuitable for
inline substitution. Among these
usages are: use of varargs, use of
alloca, use of variable sized data
types (see Variable Length), use of
computed goto (see Labels as Values),
use of nonlocal goto, and nested
functions (see Nested Functions).
Using -Winline will warn when a
function marked inline could not be
substituted, and will give the reason
for the failure.

As required by ISO C++, GCC considers
member functions defined within the
body of a class to be marked inline
even if they are not explicitly
declared with the inline keyword. You
can override this with
-fno-default-inline; see Options Controlling C++ Dialect.

GCC does not inline any functions when
not optimizing unless you specify the
`always_inline' attribute for the
function, like this:

 /* Prototype.  */
 inline void foo (const char) __attribute__((always_inline)); The remainder of this section is specific

to GNU C90 inlining.

When an inline function is not static,
then the compiler must assume that
there may be calls from other source
files; since a global symbol can be
defined only once in any program, the
function must not be defined in the
other source files, so the calls
therein cannot be integrated.
Therefore, a non-static inline
function is always compiled on its own
in the usual fashion.

If you specify both inline and extern
in the function definition, then the
definition is used only for inlining.
In no case is the function compiled on
its own, not even if you refer to its
address explicitly. Such an address
becomes an external reference, as if
you had only declared the function,
and had not defined it.

This combination of inline and extern
has almost the effect of a macro. The
way to use it is to put a function
definition in a header file with these
keywords, and put another copy of the
definition (lacking inline and extern)
in a library file. The definition in
the header file will cause most calls
to the function to be inlined. If any
uses of the function remain, they will
refer to the single copy in the
library.

德意的啸 2024-10-27 20:37:00

提示的强度完全取决于您使用的编译选项。大多数编译器都可以选择不进行内联,仅内联那些标记为“内联”的内容,或者使用其最佳判断并忽略提示。

最后一个可能效果最好。 :-)

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. :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文