简体   繁体   English

我如何告诉 gcc 不要内联函数?

[英]How can I tell gcc not to inline a function?

Say I have this small function in a source file假设我在源文件中有这个小函数

static void foo() {}

and I build an optimized version of my binary yet I don't want this function inlined (for optimization purposes).我构建了我的二进制文件的优化版本,但我不想内联此函数(出于优化目的)。 is there a macro I can add in a source code to prevent the inlining?有没有我可以在源代码中添加的宏来防止内联?

You want the gcc -specific noinline attribute.您需要特定于gcc noinline属性。

This function attribute prevents a function from being considered for inlining.此函数属性可防止考虑内联函数。 If the function does not have side-effects, there are optimizations other than inlining that causes function calls to be optimized away, although the function call is live.如果函数没有副作用,除了内联之外还有其他优化会导致函数调用被优化掉,尽管函数调用是实时的。 To keep such calls from being optimized away, put asm ("");为了防止这些调用被优化掉,把asm ("");

Use it like this:像这样使用它:

void __attribute__ ((noinline)) foo() 
{
  ...
}

GCC has a switch called GCC 有一个开关叫做

-fno-inline-small-functions

So use that when invoking gcc.所以在调用 gcc 时使用它。 But the side effect is that all other small functions are also non-inlined.但副作用是所有其他小函数也是非内联的。

A portable way to do this is to call the function through a pointer:一种可移植的方法是通过指针调用函数:

void (*foo_ptr)() = foo;
foo_ptr();

Though this produces different instructions to branch, which may not be your goal.尽管这会产生不同的分支指令,但这可能不是您的目标。 Which brings up a good point: what is your goal here?这提出了一个好观点:你在这里的目标什么?

I know the question is about GCC, but I thought it might be useful to have some information about compilers other compilers as well.我知道这个问题是关于 GCC 的,但我认为获得一些关于编译器和其他编译器的信息可能会很有用。

GCC's noinline function attribute is pretty popular with other compilers as well. GCC 的noinline函数属性在其他编译器中也很受欢迎。 It is supported by at least:它至少得到以下支持:

  • Clang (check with __has_attribute(noinline) ) Clang(检查__has_attribute(noinline)
  • Intel C/C++ Compiler (their documentation is terrible, but I'm certain it works on 16.0+) Intel C/C++ Compiler(他们的文档很糟糕,但我确定它适用于 16.0+)
  • Oracle Solaris Studio back to at least 12.2 Oracle Solaris Studio 至少回到 12.2
  • ARM C/C++ Compiler back to at least 4.1 ARM C/C++ 编译器至少回到 4.1
  • IBM XL C/C++ back to at least 10.1 IBM XL C/C++ 至少回到 10.1
  • TI 8.0+ (or 7.3+ with --gcc, which will define __TI_GNU_ATTRIBUTE_SUPPORT__ ) TI 8.0+(或带有 --gcc 的 7.3+,它将定义__TI_GNU_ATTRIBUTE_SUPPORT__

Additionally, MSVC supports __declspec(noinline) back to Visual Studio 7.1.此外,MSVC 支持__declspec(noinline)回到 Visual Studio 7.1。 Intel probably supports it too (they try to be compatible with both GCC and MSVC), but I haven't bothered to verify that.英特尔可能也支持它(他们试图与 GCC 和 MSVC 兼容),但我没有费心去验证。 The syntax is basically the same:语法基本相同:

__declspec(noinline)
static void foo(void) { }

PGI 10.2+ (and probably older) supports a noinline pragma which applies to the next function: PGI 10.2+(可能更旧)支持适用于下一个函数的noinline pragma:

#pragma noinline
static void foo(void) { }

TI 6.0+ supports a FUNC_CANNOT_INLINE pragma which (annoyingly) works differently in C and C++. TI 6.0+ 支持FUNC_CANNOT_INLINE编译指示,它(令人讨厌)在 C 和 C++ 中的工作方式不同。 In C++, it's similar to PGI's:在 C++ 中,它类似于 PGI:

#pragma FUNC_CANNOT_INLINE;
static void foo(void) { }

In C, however, the function name is required:然而,在 C 中,函数名是必需的:

#pragma FUNC_CANNOT_INLINE(foo);
static void foo(void) { }

Cray 6.4+ (and possibly earlier) takes a similar approach, requiring the function name: Cray 6.4+(可能更早版本)采用了类似的方法,需要函数名:

#pragma _CRI inline_never foo
static void foo(void) { }

Oracle Developer Studio also supports a pragma which takes the function name, going back to at least Forte Developer 6 , but note that it needs to come after the declaration, even in recent versions: Oracle Developer Studio 还支持采用函数名称的编译指示, 至少可以追溯到Forte Developer 6 ,但请注意,即使在最近的版本中,它也需要在声明之后出现:

static void foo(void);
#pragma no_inline(foo)

Depending on how dedicated you are, you could create a macro that would work everywhere, but you would need to have the function name as well as the declaration as arguments.根据您的专注程度,您可以创建一个可以在任何地方使用的宏,但您需要将函数名称和声明作为参数。

If, OTOH, you're okay with something that just works for most people, you can get away with something which is a little more aesthetically pleasing and doesn't require repeating yourself. OTOH,如果您对适合大多数人的东西感到满意,那么您可以摆脱一些更美观且不需要重复自己的东西。 That's the approach I've taken for Hedley , where the current version of HEDLEY_NEVER_INLINE looks like:这就是我为Hedley采取的方法,其中HEDLEY_NEVER_INLINE的当前版本如下所示:

#if \
  HEDLEY_GNUC_HAS_ATTRIBUTE(noinline,4,0,0) || \
  HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
  HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
  HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
  HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
  HEDLEY_TI_VERSION_CHECK(8,0,0) || \
  (HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
#  define HEDLEY_NEVER_INLINE __attribute__((__noinline__))
#elif HEDLEY_MSVC_VERSION_CHECK(13,10,0)
#  define HEDLEY_NEVER_INLINE __declspec(noinline)
#elif HEDLEY_PGI_VERSION_CHECK(10,2,0)
#  define HEDLEY_NEVER_INLINE _Pragma("noinline")
#elif HEDLEY_TI_VERSION_CHECK(6,0,0)
#  define HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
#else
#  define HEDLEY_NEVER_INLINE HEDLEY_INLINE
#endif

If you don't want to use Hedley (it's a single public domain / CC0 header) you can convert the version checking macros without too much effort, but more than I'm willing to put in ☺.如果您不想使用 Hedley(它是单个公共域/CC0 标头),您可以毫不费力地转换版本检查宏,但比我愿意投入的要多 ☺。

In case you get a compiler error for __attribute__((noinline)) , you can just try:如果您收到__attribute__((noinline))的编译器错误,您可以尝试:

noinline int func(int arg)
{
    ....
}
static __attribute__ ((noinline))  void foo()
{

}

This is what worked for me.这对我有用。

Use the noinline attribute :使用noinline属性

int func(int arg) __attribute__((noinline))
{
}

You should probably use it both when you declare the function for external use and when you write the function.在声明函数供外部使用时和编写函数时,您可能都应该使用它。

I work with gcc 7.2.我使用 gcc 7.2。 I specifically needed a function to be non-inlined, because it had to be instantiated in a library.我特别需要一个非内联函数,因为它必须在库中实例化。 I tried the __attribute__((noinline)) answer, as well as the asm("") answer.我尝试了__attribute__((noinline))答案,以及asm("")答案。 Neither one solved the problem.没有一个人解决了这个问题。

Finally, I figured that defining a static variable inside the function will force the compiler to allocate space for it in the static variable block, and to issue an initialization for it when the function is first called.最后,我认为在函数内定义一个静态变量将迫使编译器在静态变量块中为其分配空间,并在首次调用该函数时为其发出初始化。

This is sort of a dirty trick, but it works.这是一个肮脏的把戏,但它有效。

I couldn't get __attribute__((noinline)) to work, but this works on clang and GCC.我无法让__attribute__((noinline))工作,但这适用于 clang 和 GCC。

The Linux kernel defines noinline . Linux 内核定义了noinline

include/linux/compiler_attributes.h:#define noinline __attribute__((__noinline__))
#include <linux/kernel.h>
static noinline void foo(void);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM