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

时间:2009-09-24 20:39:34

标签: c gcc inline

说我在源文件中有这个小功能

static void foo() {}

我构建了二进制文件的优化版本,但我不希望这个函数内联(出于优化目的)。我可以在源代码中添加一个宏来阻止内联吗?

8 个答案:

答案 0 :(得分:130)

您需要gcc特定的noinline属性。

  

此功能属性可防止a   正在考虑的功能   内联。如果功能没有   有副作用,有   除了内联之外的优化   导致函数调用被优化   离开,虽然函数调用是   生活。保持这样的呼叫   优化了,放             asm ("");

像这样使用:

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

答案 1 :(得分:26)

GCC有一个名为

的开关

-fno-inline-small-functions

所以在调用gcc时使用它。但副作用是所有其他小功能也都是非内联的。

答案 2 :(得分:21)

执行此操作的可移植方法是通过指针调用该函数:

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

虽然这会产生不同的分支指令,但这可能不是你的目标。这提出了一个好点: 你的目标是什么?

答案 3 :(得分:13)

如果__attribute__((noinline))出现编译错误,您可以尝试:

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

答案 4 :(得分:10)

我知道这个问题是关于海湾合作委员会的,但我认为它可能有用 有关编译器其他编译器的一些信息。

GCC的 noinline 函数属性也很受其他编译器的欢迎。它 至少得到支持:

  • Clang(查看__has_attribute(noinline)
  • 英特尔C / C ++编译器(他们的文档非常糟糕,但我是 确定它适用于16.0 +)
  • Oracle Solaris Studio至少返回12.2
  • ARM C / C ++编译器至少返回4.1
  • IBM XL C / C ++至少回到10.1
  • TI 8.0+(或7.3+ with --gcc,将定义__TI_GNU_ATTRIBUTE_SUPPORT__

此外,MSVC支持 __declspec(noinline) 回到Visual Studio 7.1。英特尔也可能支持它(他们试图 兼容GCC和MSVC),但我没有打扰 验证。语法基本相同:

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

PGI 10.2+(可能更旧)支持noinline编译指示 适用于下一个功能:

#pragma noinline
static void foo(void) { }

TI 6.0+支持a FUNC_CANNOT_INLINE pragma(烦人地)在C和C ++中的工作方式不同。在C ++中,它类似于PGI:

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

但是,在C中,函数名称是必需的:

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

Cray 6.4+(可能更早)采用类似的方法,需要 功能名称:

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

Oracle Developer Studio还支持一个pragma,它接受了 功能名称,返回at least Forte Developer 6, 但请注意,即使在最近,它也需要在声明之后来 版本:

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

根据您的奉献精神,您可以创建一个宏 可以在任何地方工作,但你需要将函数名称作为 以及作为论据的声明。

如果,OTOH,你可以选择适合大多数人的东西, 你可以摆脱一些更美观的东西 赏心悦目,不需要重复自己。这就是方法 我已经选择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_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
#else
#  define HEDLEY_NEVER_INLINE HEDLEY_INLINE
#endif

如果您不想使用Hedley(它是一个公共领域/ CC0 header)你可以毫不费力地转换版本检查宏 努力,但比我愿意投入更多。

答案 5 :(得分:9)

static __attribute__ ((noinline))  void foo()
{

}

这对我有用。

答案 6 :(得分:7)

使用noinline attribute

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

当您声明外部使用的函数和编写函数时,您应该使用它。

答案 7 :(得分:1)

我使用gcc 7.2。我特别需要一个非内联函数,因为它必须在库中实例化。我尝试了__attribute__((noinline))答案,以及asm("")答案。两个人都没有解决问题。

最后,我认为在函数内部定义静态变量会强制编译器在静态变量块中为它分配空间,并在首次调用函数时为它发出初始化。

这有点肮脏,但它有效。