Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calls that precede a function's definition cannot be inlined?

Tags:

c++

c

gcc

g++

inlining

The gcc documentation contains the following:

When a function is both inline and static, if all calls to the function are integrated into the caller, and the function's address is never used, then the function's own assembler code is never referenced. In this case, GCC does not actually output assembler code for the function, unless you specify the option -fkeep-inline-functions. Some calls cannot be integrated for various reasons (in particular, calls that precede the function's definition cannot be integrated, and neither can recursive calls within the definition).

That always sounded absurd to me -- why would a modern compiler be that dumb? After a quick test it does seem untrue.

The test code:

static inline int foo();

int bar() {
    return foo();
}

int foo() {
    return 42;
}

The result with gcc-4.9.2 on Linux contains code for bar() but none for foo(). You can see that foo() has been integrated:

bar:
.LFB0:
    .cfi_startproc
    movl    $42, %eax
    ret
    .cfi_endproc

If I compile as C++ the result is the same, except for name mangling.

Contrary to the documentation, despite foo() being defined after the call in bar(), foo() has been completely integrated into bar().

Do I misunderstand the documentation or is it incorrect? Perhaps it's correct for some more complicated case?

I don't know if there's a technical distinction between "integrate" and "inline" but I suspect "integrate" is being used to distinguish from keyword inline and it just refers to function inlining (hence the title).

This question is tagged as C and C++ because this portion of the gcc documentation pertains to the "C language family" and I expect the answer to be the same for the two languages.

like image 971
Praxeolitic Avatar asked Feb 06 '15 12:02

Praxeolitic


People also ask

What functions Cannot be inlined?

A function containing static variables cannot be made an inline function.

How do you check if a function is inlined or not?

The most reliable way to see if a function is being inlined or not is to look at the output from the compiler. Most compilers have a switch to output assembler code for your inspection.

Can all functions be inlined?

First, you cannot always inline, e.g. recursive functions might not be always inlinable (but a program containing a recursive definition of fact with just a printing of fact(8) could be inlined). Then, inlining is not always beneficial.

When can a function be inlined?

Only when you want the function to be defined in a header. More exactly only when the function's definition can show up in multiple translation units. It's a good idea to define small (as in one liner) functions in the header file as it gives the compiler more information to work with while optimizing your code.


1 Answers

Gcc used to compile and optimize one function at a time, as soon as they were parsed, before parsing the next one. IIRC, it is only in the 4.X time frame that they introduced the -funit-at-a-time option which postponed the optimization to after having read the whole compilation unit and then they waited some releases to enable it by default.

The possibility of inlining function defined after the call has probably be introduced as part of the -funit-at-a-time work, and the documentation of inline (the mention about calls preceding the definition dates back at least to 2.95) has not updated then.

like image 175
AProgrammer Avatar answered Sep 25 '22 03:09

AProgrammer