Can a very short function become inlined even if it was not explicitly defined as inline?
Asked Answered
A

4

7

I know in advance that, when writing a program in C or C++, even if I declare a function as "inline" the compiler is free to ignore this and decide not to expand it at each (or any) call.

Is the opposite true as well? That is, can a compiler automatically inline a very short function that wasn't defined as inline if the compiler believes doing so will lead to a performance gain?

Two other subquestions: is this behaviour defined somewhere in the ANSI standards? Is C different from C++ in this regard, or do they behave the same?

Allhallowmas answered 27/11, 2018 at 15:46 Comment(12)
Look up the "as-if rule".Turgite
Is the opposite true as well? Yes it is. as @Turgite mentioned the "as-if rule" is the one that allows this.Systematics
#1759800Roca
@Systematics Can you please say it as an answer? If possible, citing some ANSI documents, or somewhere else that explicitely says so?Allhallowmas
Mats link is not a perfect dupe but the top answer to the question should have all you needPersonify
There are users that are more knowledgeable on the specifics of the standards. Also I no longer can claim to know the c standards since I last looked at that sometime in the 1990s. My comment above was just about c++Systematics
The inline keyword is maybe a hint for the compiler. It has nothing to do anymore with whether or not inlineing occurs.Postmeridian
gcc -finline-function option : "Consider all functions for inlining, even if they are not declared inline. The compiler heuristically decides which functions are worth integrating in this way". Source : gcc.gnu.orgKakemono
@FrançoisAndrieux the point is: I recently entered a debate with a coworker who argues that if I don't mark a function as "inline" it's as though I'm declaring it to be "offline", so he doesn't believe the compiler can inline it, ever, if it's not explicitely declared inline. To the best of my knowledge yes, the compiler can inline functions not declared as "inline", so I want to settle the discussion but need refferences to official documentsAllhallowmas
@JoePineda: The only "ANSI" Standard would have been ANSI C in 1989. C was promoted to an International Standard the next year, with only trivial changes. (ISO C90). C++ has its own standards, made by another ISO workgroup, and its first version was already an International Standard (ISO C++'98). Current versions are ISO C'11 and ISO C++17.Fiorenze
In C, the compiler can, and sometimes does, inline a very big function that is defined as static (so it is only visible from the one source file) and is only called once in that file, and never gets used via a pointer to function. Apart from the use of static (anonymous namespace?), the same probably applies to C++.Microsome
Your coworker is party right. If you don't mark a function inline, then you have to put that function in a .cpp file. So the compiler won't see the implementation of it, it cannot be inlined into other translation units. Two exceptions: if you mark that function static, then you can put it into a header file. The other exception is LTO (link time optimization). But for the default case (function in a .cpp file, without LTO), the compiler won't (because it cannot) inline the function, if it is in another compilation unit.Keshiakesia
L
12

inline is non-binding with regards to whether or not a function will be inlined by the compiler. This was originally what it was intended to do. But since then, it's been realized that whether or not a function is worth inlining depends as much on the call site as the function itself and is best left to the compiler to decide.

From https://en.cppreference.com/w/cpp/language/inline :

Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above.

Edit : Since you asked for C as well, from https://en.cppreference.com/w/c/language/inline :

The intent of the inline specifier is to serve as a hint for the compiler to perform optimizations, such as function inlining, which require the definition of a function to be visible at the call site. The compilers can (and usually do) ignore presence or absence of the inline specifier for the purpose of optimization.

Leola answered 27/11, 2018 at 15:59 Comment(5)
Excellent! Quick question: Is there a significant difference for C vs. C++ on this? Or are C compilers forced to never ever expand a function that's not declared as inline?Allhallowmas
@JoePineda Updated with a quote from the C inline page on cppreference.Postmeridian
So, in a nutshell: both C and C++ compilers can inline a function not explicitely declared as inline if such compiler believes this will lead to a performance improvement, right?Allhallowmas
@JoePineda Yes. Just let the compiler implement the micro optimizations for you, modern compilers are usually very very good at that.Postmeridian
Very, very few people can out-optimize a compiler, and their code usually looks like it was written by a deranged lunatic.Battue
C
2

Regarding the relation between C and C++, the inline specifier is treated differently in each language.

  • In C++: inline functions (and function like entities, and variables (since C++17) ) that have not been previously declared with internal linkage will have external linkage and be visible from other compilation units. Since inline functions (usually) reside in header files, this means that the same function will have repeated definitions across different compilation units (this is would be a violation of the One definition rule but the inline makes it legal). At the end of the build process (when linking an executable or a shared lib), inline definitions of the same entity are merged together. Informally, C++ inline means: "there may be multiple identical definitions of some function across multiple source files, but I want them to end up as a unique definition".
  • In C: If extern is not explicitly specified, then an inline function definition is not visible from other translation units, different translation units may have different definitions with inline specifier for the same function name. Also, there may exist (at most) one definition for a function name that is both inline and extern and this qualifies that function as the one that is externally visible (ie gets selected when one applies the address of & operator to the function name). The One definition rule from C and its relation with extern and inline is somehow different from C++.
Couperin answered 27/11, 2018 at 18:38 Comment(0)
P
1

can a compiler automatically inline a very short function that wasn't defined as inline if the compiler believes doing so will lead to a performance gain?

Limitation:
When code uses a pointer to the function, then the function needs to exist non-inlined.

Limitation:
When the function is visible outside the local .c file (not static), this prevents simplistic inlined code.

Not a limitation:
The length of the function is not an absolute limitation, albeit a practical one.

I've worked with embedded processor that commonly inline static functions. (Given code does not use a pointer to them.)

The usefulness of the inline keyword does not affect the ability for a compiler to inline function.

Peccadillo answered 27/11, 2018 at 17:24 Comment(3)
Regarding first Limitation: Value-(Range-)Propagation might help out there. Regarding the second, what does simplistic mean there?Stew
@Stew "simplistic" means that, from my POV, I see no reasonable way for a compiler to do so, yet compilers are ever more aggressive, so it may occur. I do not see how Value-(Range-)Propagation helps here.Peccadillo
If the compiler knows what the pointer it calls to points at, it can inline anyway. If it knows (the) N values it probably is, that might still be worthwhile for small enough N. Ok, no range there.Stew
G
0

When it comes to the standard, the keyword inline has nothing to do with inlining.

The rules (in c++) are basically:

  • A function which is not declared inline can by only defined in one translation union. It still needs to be delared in each translation unit where it is used.
  • A function which is declared inline has to be defined in each translation unit where it is odr-used (ord-use means to call the function or to take the pointer,...).

So, in a standard project setting it is almost always correct to follow the following two rules. Functions that are defined in a header file, are always to be declared inline. Functions defined in a *.cpp-file are never declared inline.

This said, I think the compiler cannot really draw any conclusions about the programmer wanted inlining from using or not using keyword inline. The name of the keyword is an unfortunate legacy from a bad naming.

Gautious answered 27/11, 2018 at 17:16 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.