Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How deep do compilers inline functions?

Say I have some functions, each of about two simple lines of code, and they call each other like this: A calls B calls C calls D ... calls K. (So basically it's a long series of short function calls.) How deep will compilers usually go in the call tree to inline these functions?

like image 344
Paul Manta Avatar asked Sep 18 '11 17:09

Paul Manta


People also ask

Do compilers inline functions?

The compiler cannot inline a function call, unless it has the full definition.

Do compilers ignore inline?

"Inline" is just a hint that the compiler is free to ignore. You can try using the always_inline function attribute. Glancing through the XC16 source code, there does seem to be some Microchip-specific code relating to when inlining is and isn't allowed.

Do compilers automatically inline?

Automatic function inlining and static functions At -O2 and -O3 levels of optimization, or when --autoinline is specified, the compiler can automatically inline functions if it is practical and possible to do so, even if the functions are not declared as __inline or inline .

Does inline function reduce code size?

Inline functions can increase the code size of your application and add stress to the instruction cache.


2 Answers

The question is not meaningful.

If you think about inlining, and its consequences, you'll realise it:

  • Avoids a function call (with all the register saving/frame adjustment)
  • Exposes more context to the optimizer (dead stores, dead code, common sub-expression elimintation...)
  • Duplicates code (bloating the instruction cache and the executable size, among other things)

When deciding whether to inline or not, the compiler thus performs a balancing act between the potential bloat created and the speed gain expected. This balancing act is affected by options: for gcc -O3 means optimize for speed while -Oz means optimize for size, on inlining they have quasi opposite behaviors!

Therefore, what matters is not the "nesting level" it is the number of instruction (possibly weighted as not all are created equal).

This means that a simple forwarding function:

int foo(int a, int b) { return foo(a, b, 3); }

is essentially "transparent" from the inlining point of view.

One the other hand, a function counting a hundred lines of code is unlikely to get inlined. Except that a static free functions called only once are quasi systematically inlined, as it does not create any duplication in this case.

From this two examples we get a hunch of how the heuristics behave:

  • the less instructions the function have, the better for inling
  • the less often it is called, the better for inlining

After that, they are parameters you should be able to set to influence one way or another (MSVC as __force_inline which hints strongly at inling, gcc as they -finline-limit flag to "raise" the treshold on the instruction count, etc...)


On a tangent: do you know about partial inlining ?

It was introduced in gcc in 4.6. The idea, as the name suggests, is to partially inline a function. Mostly, to avoid the overhead of a function call when the function is "guarded" and may (in some cases) return nearly immediately.

For example:

void foo(Bar* x) {
  if (not x) { return; } // null pointer, pfff!

  // ... BIG BLOC OF STATEMENTS ...
}

void bar(Bar* x) {
  // DO 1
  foo(x);
  // DO 2
}

could get "optimized" as:

void foo@0(Bar* x) {
  // ... BIG BLOC OF STATEMENTS ...
}

void bar(Bar* x) {
  // DO 1
  if (x) { foo@0(x); }
  // DO 2
}

Of course, once again the heuristics for inlining apply, but they apply more discriminately!


And finally, unless you use WPO (Whole Program Optimization) or LTO (Link Time Optimization), functions can only be inlined if their definition is in the same TU (Translation Unit) that the call site.

like image 94
Matthieu M. Avatar answered Oct 01 '22 16:10

Matthieu M.


I've seen compilers inline more than 5 functions deep. But at some point, it basically becomes a space-efficiency trade-off that the compiler makes. Every compiler is different in this aspect. Visual Studio is very conservative with inlining. GCC (under -O3) and the Intel Compiler love to inline...

like image 45
Mysticial Avatar answered Oct 01 '22 16:10

Mysticial