How can I tell gcc not to inline a function?

131,645

Solution 1

You want the gcc-specific noinline attribute.

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 ("");

Use it like this:

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

Solution 2

GCC has a switch called

-fno-inline-small-functions

So use that when invoking gcc. But the side effect is that all other small functions are also non-inlined.

Solution 3

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's noinline function attribute is pretty popular with other compilers as well. It is supported by at least:

  • Clang (check with __has_attribute(noinline))
  • Intel C/C++ Compiler (their documentation is terrible, but I'm certain it works on 16.0+)
  • Oracle Solaris Studio back to at least 12.2
  • ARM C/C++ Compiler back to at least 4.1
  • IBM XL C/C++ back to at least 10.1
  • TI 8.0+ (or 7.3+ with --gcc, which will define __TI_GNU_ATTRIBUTE_SUPPORT__)

Additionally, MSVC supports __declspec(noinline) back to 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. 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:

#pragma noinline
static void foo(void) { }

TI 6.0+ supports a FUNC_CANNOT_INLINE pragma which (annoyingly) works differently in C and C++. In C++, it's similar to PGI's:

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

In C, however, the function name is required:

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

Cray 6.4+ (and possibly earlier) takes a similar approach, requiring the function name:

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

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. That's the approach I've taken for Hedley, where the current version of HEDLEY_NEVER_INLINE looks like:

#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 ☺.

Solution 4

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?

Solution 5

In case you get a compiler error for __attribute__((noinline)), you can just try:

noinline int func(int arg)
{
    ....
}
Share:
131,645

Related videos on Youtube

vehomzzz
Author by

vehomzzz

He adapts a lazy approach to a complex learning. His eclectic personality coupled with eccentric character caused much harm to masses, and to himself.

Updated on November 28, 2020

Comments

  • vehomzzz
    vehomzzz about 2 years

    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?

  • John Greene
    John Greene almost 6 years
    Didn't work at compiler level. Was using gcc 5.2.1 20150902 (Red Hat 5.2.1-2)
  • ajeh
    ajeh over 4 years
    Either current GCC 6.4 is broken, or this and simpler -fno-inline do not work at all. gdb still enters methods on step-over. Something is broken, and I doubt it is gdb.
  • Daisuke Aramaki
    Daisuke Aramaki almost 4 years
    Thanks for the link to your project @nemequ. I've asked our other developers to evaluate it for our use. We have diverse architectures.
  • nemequ
    nemequ almost 4 years
    I'd be very interested to know what they say, especially if they're not interested. And, of course, I'm around to answer questions (GitHub issue tracker, e-mail, whatever…).
  • where23
    where23 over 3 years
    It will turn off inline optimization for all, not only for a specified function.
  • Melebius
    Melebius over 2 years
    @ajeh Not inlining functions means that they are called normally, doesn’t it?

Related