3

I am trying to get the expected behavior when I use the keyword inline. I tried calling a function in different files, templating the function, using different implementation of the inline function, but whatever I do, the compiler is never inlining the function.

So in which case exactly will the compiler chose to inline a function in C++ ?

Here is the code I have tried :

inline auto Add(int i) -> int {
  return i+1;
}

int main() {  
  Add(1);  
  return 0;
}

In this case, I get:

Add(int):
    pushq   %rbp
    movq    %rsp, %rbp
    movl    %edi, -4(%rbp)
    movl    -4(%rbp), %eax
    addl    $1, %eax
    popq    %rbp
    ret
main:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $1, %edi
    call    Add(int)
    movl    $0, %eax
    popq    %rbp
    ret

Or again,

template<typename T>
inline auto Add(const T &i) -> decltype(i+1) {
  return i+1;
}

int main() {  
  Add(1);  
  return 0;
}

And I got:

main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movl    $1, -4(%rbp)
    leaq    -4(%rbp), %rax
    movq    %rax, %rdi
    call    decltype ({parm#1}+(1)) Add<int>(int const&)
    movl    $0, %eax
    leave
    ret
decltype ({parm#1}+(1)) Add<int>(int const&):
    pushq   %rbp
    movq    %rsp, %rbp
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    (%rax), %eax
    addl    $1, %eax
    popq    %rbp
    ret

I used https://gcc.godbolt.org/ to get the assembly code here, but I also tried on my machine with clang and gcc (with and without optimization options).

EDIT:

Ok, I was missing something with the optimization options. If I set GCC to use o3 optimization level, my method is inlined.

But still. How does GCC, or another compiler, know when it is better to inline a function or not ?

Thibaut Mattio
  • 822
  • 9
  • 17
  • 4
    You should not care. The optimizing compiler is smarter than you on inlining decisions. – Basile Starynkevitch Jun 13 '15 at 22:24
  • 1
    `inline` is a hint that is often ignored (although you often can force it back with a compiler option), the compiler knows better how to inline in the vast majority of cases. The keyword still has some other uses, but not really this. [Related](http://stackoverflow.com/questions/1759300/when-should-i-write-the-keyword-inline-for-a-function-method). – tux3 Jun 13 '15 at 22:25
  • On Debian/Sid/x86-64 with GCC 4.9.2 invoked as `g++ -fverbose-asm -std=c++14 -O3 -S e.cc` the compiler *is* inlining your first example and `main` becomes empty -.e.g. compiled like `return 0;` (since without observable side effects) – Basile Starynkevitch Jun 13 '15 at 22:28
  • Also, be careful: sometimes using the inline keyword can decrease performance. There's a lot of information floating around about inlining and not all of it is accurate, simply because its use depends so much on the particulars of the situation. Some light reading: https://isocpp.org/wiki/faq/inline-functions#inline-and-perf – SamuelMS Jun 13 '15 at 22:32
  • @SamuelMS: Sadly, that FAQ completely misses the point that `inline` as a keyword has practically _no_ bearing in the modern day and age as to whether a function shall be inlined. (Consequently, I'd expect using it to "decrease performance" almost never). – Lightness Races in Orbit Jun 13 '15 at 22:54
  • @BasileStarynkevitch I was certainly missing something with the optimizations options, but with the -O3 (and -O2) option, I have the expected behavior. The compiler seems to consider the `inline` flag and chose either if it wants to inline the function or not. On my [example](https://goo.gl/neHJ0S), the compiler chose to inline the method if it is less than 10 line. 10 line is also the recommended size to inline functions according to [Google](https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Inline_Functions) – Thibaut Mattio Jun 13 '15 at 23:14
  • Note that inline functions are a real pain when it comes to debugging. On many systems, you can't even set breakpoints or step into inline functions. – cup Jun 13 '15 at 23:41

2 Answers2

6

As a rule, your code is always inlined only if you specify:

__attribute__((always_inline))

eg (from gcc documentation):

inline void foo (const char) __attribute__((always_inline));

Though it is almost never a good idea to force your compiler to inline your code.

You may set a high optimization level (though the O flag) to achieve maximum inlining, but for more details please see the gcc documentation

Inlining is actually controlled by a number of parameters. You can set them using the -finline-* options. You can have a look at them here

Yogesh
  • 740
  • 2
  • 7
  • 15
0

By the way, you did not actually declare a function. You declared a functor, an object that can be called, but can also store state. Instead of using the syntax:
inline auto Add(int i) -> int {

you mean to say simply:
inline int Add(int i) {

CHKingsley
  • 321
  • 2
  • 9
  • This is not a functor, just another way to specify the return type of your functions. C++11 does not allow you to deduce the return type of a function, but it does allow you to specify the type after the function signature. Which is specially useful with templates. For more information: http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html – Thibaut Mattio Jun 14 '15 at 08:13
  • Thibaut Mattio is correct. I was confused by the similarity of the syntax to a lambda expression. – CHKingsley Jun 14 '15 at 23:57