76

Does __attribute__((always_inline)) force a function to be inlined by gcc?

Cole Tobin
  • 9,206
  • 15
  • 49
  • 74
HaltingState
  • 1,810
  • 1
  • 20
  • 22
  • 41
    GCC uses code size as heuristic to determine whether something will be inlined. I have a networking/serialization library where it wont inline functions by default because of code size. I did inlining and it improved performance 30% in benchmark. One reason to inline, is if you know values at compile time (consts are passed in) and you want to flatten the function. For instance if a function is used in two different places with different static parameters, inlining can reduce branches. This is for functions usd in an inner loop. – HaltingState Dec 11 '11 at 11:40
  • 1
    Another example reason: I do audio DSP coding. Sometimes I can't use the debugger because the non-inlined function calls (from lots of accessor functions and stuff) become so expensive the code can't service the buffer fast enough. – DCBillen Sep 25 '14 at 12:57
  • 2
    Just as a reminder ... you need to specify both `inline` and `__attribute__((always_inline))`. I just tested this on Android NDK r10d with GCC. Perhaps not a standard environment but from what I've read this requirement is the same for all platforms. – rwong Apr 10 '15 at 06:28
  • 3
    Another example (not optimization-based): When writing a function for a microcontroller to write to its internal flash at runtime, I need to copy the routine that does the actual writing out of flash and into ram before starting the write, as simultaneous reads and writes are not allowed. If this routine calls any non-inlined functions, then I would have to copy all dependencies into ram and dynamically adjust any jump addresses, which is way more complex than the force-inline solution. – Ponkadoodle Aug 03 '15 at 17:40
  • 1
    Force inlining provides something akin at least portion of non-type template parameters in C++: when you know you want a new function compiled for each value of a parameter. You could try to use macros to get this ability, but force-inlining is often cleaner (although less portable). – BeeOnRope Mar 11 '17 at 18:06
  • One exception is that gcc will not inline functions with variable argument lists `int forexample ( const char * fmt, ... );` – John Hascall Sep 29 '17 at 14:37
  • Think of inline functions returning V8 handles. How would I know whether I should `.Escape()` the handles or not, if the functions are not ensured to be inline? If the compiler fails to inline such functions, V8 will make new handle scopes! – Константин Ван Mar 11 '18 at 18:12

8 Answers8

54

Yes.

always_inline

Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level was specified.

Community
  • 1
  • 1
RCE
  • 1,681
  • 13
  • 12
40

It should. I'm a big fan of manual inlining. Sure, used in excess it's a bad thing. But often times when optimizing code, there will be one or two functions that simply have to be inlined or performance goes down the toilet. And frankly, in my experience C compilers typically do not inline those functions when using the inline keyword.

I'm perfectly willing to let the compiler inline most of my code for me. It's only those half dozen or so absolutely vital cases that I really care about. People say "compilers do a good job at this." I'd like to see proof of that, please. So far, I've never seen a C compiler inline a vital piece of code I told it to without using some sort of forced inline syntax (__forceinline on msvc __attribute__((always_inline)) on gcc).

Joe
  • 508
  • 4
  • 4
  • 7
    I appreciate the msvc vs. gcc comparison! – Zak Dec 11 '14 at 01:35
  • 11
    I agree but I force inlining way more than it. I use __forceinline on thousands of functions and have saved 20% of a 600 server farm. Assuming that the compiler will make the best decision WRT inlining is simply not true. The compiler is guessing. Educated guess or not, it is still a guess. The compiler doesn't know that you wrote the function to optimize out expressions formed with constant parameters. Etc etc etc. – johnnycrash Mar 14 '16 at 17:15
  • 4
    with gcc you also need to specify `inline` explicitly: `__attribute__((always_inline)) inline YourFunc(...` else you will get `warning: always_inline function might not be inlinable [-Wattributes]` – slashmais Aug 15 '18 at 03:48
23

Yes, it will. That doesn't necessarily mean it's a good idea.

jmkeyes
  • 3,751
  • 17
  • 20
  • Inlining a function won't always improve performance (e.g. cache issues). – Basile Starynkevitch Jul 22 '12 at 14:00
  • 13
    Example of a very good reason I use it sometimes: When developing audio DSP applications sometimes the debug build can't process fast enough to keep up with the sample rate. By forcing things like accessor functions to inline I am able to test and debug. – DCBillen Dec 20 '14 at 16:17
  • 7
    Correction: it doesn't _necessarily_ mean it's a good idea. Sometimes it is. – No-Bugs Hare Sep 17 '17 at 12:42
13

According to the gcc optimize options documentation, you can tune inlining with parameters:

-finline-limit=n
By default, GCC limits the size of functions that can be inlined. This flag 
allows coarse control of this limit. n is the size of functions that can be 
inlined in number of  pseudo instructions.

Inlining is actually controlled by a number of parameters, which may be specified
individually by using --param name=value. The -finline-limit=n option sets some 
of these parameters as follows:

    max-inline-insns-single is set to n/2. 
    max-inline-insns-auto is set to n/2.

I suggest reading more in details about all the parameters for inlining, and setting them appropriately.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
6

I want to add here that I have a SIMD math library where inlining is absolutely critical for performance. Initially I set all functions to inline but the disassembly showed that even for the most trivial operators it would decide to actually call the function. Both MSVC and Clang showed this, with all optimization flags on.

I did as suggested in other posts in SO and added __forceinline for MSVC and __attribute__((always_inline)) for all other compilers. There was a consistent 25-35% improvement in performance in various tight loops with operations ranging from basic multiplies to sines.

I didn't figure out why they had such a hard time inlining (perhaps templated code is harder?) but the bottom line is: there are very valid use cases for inlining manually and huge speedups to be gained.

If you're curious this is where I implemented it. https://github.com/redorav/hlslpp

RedOrav
  • 953
  • 9
  • 21
  • 2
    template function code tends not to get inlined, but rather every specialization gets into a separate `.text` section in order to make "vague linkage" possible (see https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Vague-Linkage.html). By forcing inlining, you basically lose the ability to explicitly specialize template functions in different compilation units. – Géza Török Nov 13 '17 at 12:59
  • I see, thanks for the explanation @GézaTörök that explains the behavior. Most math classes are quite hard to write without templating (not to mention the perf gains), so it seems like explicitly forcing inline is often a must. – RedOrav Nov 15 '17 at 10:15
5

Yes. It will inline the function regardless of any other options set. See here.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
1

One can also use __always_inline. I have been using that for C++ member functions for GCC 4.8.1. But could not found a good explanation in GCC doc.

Jie Xu
  • 19
  • 2
-4

Actually the answer is "no". All it means is that the function is a candidate for inlining even with optimizations disabled.

DCBillen
  • 96
  • 1
  • 6
  • 6
    and yet the top answer has a direct quote that specifically says "this attribute inlines the function". I see no reference to any "candidate" there at all. What is your source? – underscore_d Jan 01 '16 at 11:13
  • 4
    This is true for the `inline` keyword, not for the `always_inline` attribute, see [here](https://stackoverflow.com/questions/20995309/difference-between-always-inline-and-inline) – Bilow Nov 04 '17 at 11:08