假设我在源文件中有一个小函数
static void foo() {}
并且我构建了我的二进制的优化版本,但是我不希望这个函数内联(为了优化的目的)。有没有一个宏我可以在源代码中添加来防止内联?
camsedfj1#
您需要特定于gcc的noinline属性。此函数属性可防止考虑对函数进行内联。如果函数没有副作用,则内联以外的优化会导致函数调用被优化掉,尽管函数调用是活动的。若要防止此类调用被优化掉,请放置asm ("");像这样使用它:
gcc
noinline
asm ("");
void __attribute__ ((noinline)) foo() { ... }
qxsslcnc2#
GCC有一个名为第一个月所以在调用gcc时使用它,但是副作用是所有其他小函数也是非内联的。
vmjh9lq93#
我知道这个问题是关于GCC的,但我认为了解一些关于编译器和其他编译器的信息可能会很有用。GCC的noinline函数属性在其他编译器中也很流行。至少有以下编译器支持它:
__has_attribute(noinline)
__TI_GNU_ATTRIBUTE_SUPPORT__
此外,MSVC支持__declspec(noinline),甚至Visual Studio 7.1也支持它。Intel可能也支持它(他们试图同时兼容GCC和MSVC),但我没有费心去验证它。
__declspec(noinline)
__declspec(noinline) static void foo(void) { }
PGI 10.2+(可能更早)支持应用于下一个函数的noinline杂注:
#pragma noinline static void foo(void) { }
TI 6.0+支持FUNC_CANNOT_INLINE杂注,但在C和C中,它的工作方式不同。在C中,它类似于PGI:
FUNC_CANNOT_INLINE
#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还支持接受函数名的杂注,可以追溯到at least Forte Developer 6,但请注意,即使在最新版本中,它也需要出现在声明的 * 之后 *:
static void foo(void); #pragma no_inline(foo)
根据你的专注程度,你可以创建一个在任何地方都能工作的宏,但是你需要有函数名和声明作为参数。OTOH,如果你觉得对大多数人都有效的东西没问题,你可以做一些更美观的东西,不需要重复。这就是我在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
如果你不想使用赫德利(它是一个公共域/CC 0头文件),你可以转换版本检查宏,而不需要太多的工作,但是我愿意花更多的精力在中。
oknrviil4#
一种可移植的方法是通过指针调用函数:
void (*foo_ptr)() = foo; foo_ptr();
虽然这会产生不同的分支指令,但这可能不是你的目标。这带来了一个好的观点:你的目标是什么?
h9vpoimq5#
如果您遇到__attribute__((noinline))的编译器错误,您可以尝试:
__attribute__((noinline))
noinline int func(int arg) { .... }
a8jjtwal6#
static __attribute__ ((noinline)) void foo() { }
这对我很有效。
aemubtdh7#
使用noinlineattribute:
int func(int arg) __attribute__((noinline)) { }
在声明函数供外部使用和编写函数时,可能都应该使用它。
kdfy810k8#
我使用gcc 7.2,我特别需要一个非内联函数,因为它必须在库中示例化,我尝试了__attribute__((noinline))和asm(""),但都没有解决问题。最后,我发现在函数内部定义一个静态变量将迫使编译器在静态变量块中为它分配空间,并在第一次调用函数时为它发出初始化。这是一种肮脏的伎俩,但它的工作。
asm("")
rkkpypqq9#
我无法让__attribute__((noinline))工作,但它可以在clang和GCC上工作。Linux内核定义了noinline。
include/linux/compiler_attributes.h:#define noinline __attribute__((__noinline__))
#include <linux/kernel.h> static noinline void foo(void);
9条答案
按热度按时间camsedfj1#
您需要特定于
gcc
的noinline
属性。此函数属性可防止考虑对函数进行内联。如果函数没有副作用,则内联以外的优化会导致函数调用被优化掉,尽管函数调用是活动的。若要防止此类调用被优化掉,请放置
asm ("");
像这样使用它:
qxsslcnc2#
GCC有一个名为
第一个月
所以在调用gcc时使用它,但是副作用是所有其他小函数也是非内联的。
vmjh9lq93#
我知道这个问题是关于GCC的,但我认为了解一些关于编译器和其他编译器的信息可能会很有用。
GCC的
noinline
函数属性在其他编译器中也很流行。至少有以下编译器支持它:__has_attribute(noinline)
检查)__TI_GNU_ATTRIBUTE_SUPPORT__
)此外,MSVC支持
__declspec(noinline)
,甚至Visual Studio 7.1也支持它。Intel可能也支持它(他们试图同时兼容GCC和MSVC),但我没有费心去验证它。PGI 10.2+(可能更早)支持应用于下一个函数的
noinline
杂注:TI 6.0+支持
FUNC_CANNOT_INLINE
杂注,但在C和C中,它的工作方式不同。在C中,它类似于PGI:但是,在C中,函数名是必需的:
Cray 6.4+(以及可能更早的版本)采用类似的方法,需要函数名:
Oracle Developer Studio还支持接受函数名的杂注,可以追溯到at least Forte Developer 6,但请注意,即使在最新版本中,它也需要出现在声明的 * 之后 *:
根据你的专注程度,你可以创建一个在任何地方都能工作的宏,但是你需要有函数名和声明作为参数。
OTOH,如果你觉得对大多数人都有效的东西没问题,你可以做一些更美观的东西,不需要重复。这就是我在Hedley中采用的方法,赫德利_NEVER_INLINE的当前版本如下所示:
如果你不想使用赫德利(它是一个公共域/CC 0头文件),你可以转换版本检查宏,而不需要太多的工作,但是我愿意花更多的精力在中。
oknrviil4#
一种可移植的方法是通过指针调用函数:
虽然这会产生不同的分支指令,但这可能不是你的目标。这带来了一个好的观点:你的目标是什么?
h9vpoimq5#
如果您遇到
__attribute__((noinline))
的编译器错误,您可以尝试:a8jjtwal6#
这对我很有效。
aemubtdh7#
使用
noinline
attribute:在声明函数供外部使用和编写函数时,可能都应该使用它。
kdfy810k8#
我使用gcc 7.2,我特别需要一个非内联函数,因为它必须在库中示例化,我尝试了
__attribute__((noinline))
和asm("")
,但都没有解决问题。最后,我发现在函数内部定义一个静态变量将迫使编译器在静态变量块中为它分配空间,并在第一次调用函数时为它发出初始化。
这是一种肮脏的伎俩,但它的工作。
rkkpypqq9#
我无法让
__attribute__((noinline))
工作,但它可以在clang和GCC上工作。Linux内核定义了
noinline
。