2

I've been reading again Scott Meyers' Effective C++ and more specifically Item 30 about inlining.

So I wrote the following, trying to induce that optimization with gcc 4.6.3

// test.h
class test {
public:

    inline int max(int i) { return i > 5 ? 1 : -1; }
    int foo(int);

private:
   int d;
};

// test.cpp

int test::foo(int i) { return max(i); }

// main.cpp

#include "test.h"

int main(int argc, const char *argv[]) {
    test t;
    return t.foo(argc);
}

and produced the relevant assembly using alternatively the following:

g++ -S -I. test.cpp main.cpp
g++ -finline-functions -S -I. test.cpp main.cpp

Both commands produced the same assembly as far as the inline method is concerned; I can see both the max() method body (also having a cmpl statement and the relevant jumps) and its call from foo().

Am I missing something terribly obvious? I can't say that I combed through the gcc man page, but couldn't find anything relevant standing out.

So, I just increased the optimization level to -O3 which has the inline optimizations on by default, according to:

g++ -c -Q -O3 --help=optimizers | grep inline
  -finline-functions                    [enabled]
  -finline-functions-called-once        [enabled]
  -finline-small-functions              [enabled] 

unfortunately, this optimized (as expected) the above code fragment almost out of existence. max() is no longer there (at least as an explicitly tagged assembly block) and foo() has been reduced to:

_ZN4test3fooEi:
.LFB7:
.cfi_startproc
rep
ret
.cfi_endproc

which I cannot clearly understand at the moment (and is out of research scope).

Ideally, what I would like to see, would have been the assembly code for max() inside the foo() block. Is there a way (either through cmd-line options or using a different (non-trivial?) code fragment) to produce such an output?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
compor
  • 2,239
  • 1
  • 19
  • 29
  • 1
    DOn't compile an entire program -- that will just get optimized away. Just write a free function `int f(int n) { return test().foo(n); }` and compile *that*. – Kerrek SB Aug 12 '14 at 20:46
  • 3
    `inline` is just a hint to the compiler, the compiler is free to inline functions without the `inline` keyword, or ignore the `inline` keyword entirely – Charles Salvia Aug 12 '14 at 20:48
  • 1
    Other than for amusement purposes, why would you want the compiler to inline a function, but then not optimize the resulting code. The primary benefit of inlining is to allow optimization. – Dale Wilson Aug 12 '14 at 20:54
  • 1
    BTW, you're missing a `return` in `test::foo`. – ildjarn Aug 12 '14 at 20:59
  • This isn't a solution, but for quick and dirty analysis of assembler results from compiler flags/tweaks, you can use [Compiler Explorer](http://gcc.godbolt.org). Choose compiler and settings and put code into editor - out pops assembler. Very useful. – Jordan Samuels Aug 12 '14 at 21:07
  • For more optimization fun add `-fwhole-program` to the GCC command line. Without it GCC has to assume that you might open your executable as a dynamic object and call functions (for a kind of reflection, for example). – Zan Lynx Aug 13 '14 at 01:15
  • i understand that `inline` is just a hint to the compiler and in that respect it's free to apply its optimizations in any way that it might find possible. with so many separate optimization options i thought it would be possible to see that feature clearly and *separately* in action and not having to enable an avalanche of optimizations. – compor Aug 13 '14 at 04:10
  • possible duplicate of [When should I write the keyword 'inline' for a function/method?](http://stackoverflow.com/questions/1759300/when-should-i-write-the-keyword-inline-for-a-function-method) - In particular, note *"It is said that inline hints to the compiler that you think the function should be inlined. That may have been true in 1998, but a decade later the compiler needs no such hints. Not to mention humans are usually wrong when it comes to optimizing code, so most compilers flat out ignore the 'hint'."* – Jason C Aug 13 '14 at 04:10
  • and yes it's for fun - i'll look into those options suggested and also try clang (when i find some spare time) – compor Aug 13 '14 at 04:13
  • Also, [said best here](http://stackoverflow.com/questions/145838/benefits-of-inline-functions-in-c?rq=1#comment6142669_145838): *"The basis of this question is flawed. C++ inline functions have little to do with compilers inlining during compilation. It is unfortunate that `inline` is a c++ keyword and that inlining is a compiler optimization technique."* - [deft_code](http://stackoverflow.com/users/28817/deft-code). – Jason C Aug 13 '14 at 04:14
  • Other possible duplicate; perhaps a more direct duplicate: http://stackoverflow.com/questions/1626248/does-gcc-inline-c-functions-without-the-inline-keyword?rq=1 – Jason C Aug 13 '14 at 04:16
  • By the way, methods both declared and defined inside the class (such as your `test::foo`) are implicitly `inline`. But as @Charles said, the whole thing is only meant as a hint to the compiler, and GCC often will use its own heuristics to decide what to inline or not. – Nicu Stiurca Aug 13 '14 at 04:18
  • @SchighSchagh it's in a different file (marked by the comment) for this reason - i didn't want to trigger implicit inlining and and it's on definition, not on declaration, otherwise it would apply to all methods. – compor Aug 13 '14 at 06:03
  • @JasonC i'm asking smt different - can't see how it's a duplicate and i hate quoting myself. anyhow, any idea to what spec does he refer to [here](http://stackoverflow.com/questions/1626248/does-gcc-inline-c-functions-without-the-inline-keyword?rq=1#comment1495576_1626248)? – compor Aug 13 '14 at 06:22
  • @compor Oops, I meant `test::max` would be implicitly marked as `inline` without the actual `inline` keyword. (And it the compiler would still be free to ignore it.) – Nicu Stiurca Aug 13 '14 at 14:20

1 Answers1

3

The compiler is entirely free to inline functiones even if you don't ask it to - both when you use inline keyword or not, or whether you use -finline-functions or not (although probably not if you use -fnoinline-functions - that would be contrary to what you asked for, and although the C++ standard doesn't say so, the flag becomes pretty pointless if it doesn't do something like what it says).

Next, the compiler is also not always certain that your function won't be used "somewhere else", so it will produce an out-of-line copy of most inline functions, unless it's entirely clear that it "can not possibly be called from somewhere else [for example the class is declared such that it can't be reached elsewhere].

And if you don't use the result of a function, and the function doesn't have side-effects (e.g. writing to a global variable, performing I/O or calling a function the compiler "doesn't know what it does"), then the compiler will eliminate that code as "dead" - because you don't really want unnecessary code, do you? Adding a return in front of max(i) in your foo function should help.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • i'll try with `-O3` and disable all inlining - if the compiler ignores it, then, as you said, it's pretty pointless to have it as a tweakable option. my `max()` did have a `return`, it was just truncated by mistake trying to make the post shorter. this is also the reason i used `argc`, since it is coming from the environment and the compiler can't deduce the value at compile-time and also produces much simpler assembly since i avoid using stdin and ``. basically, i'd like the bare minimum code to see inlining in action and avoid dead-code elimination. – compor Aug 13 '14 at 06:39