Some common aspects:
- Compiler option (debug builds are usually not built-in, and most compilers have options to override the built-in declaration to try to embed all or none)
- suitable calling convention (e.g. varargs functions are usually not nested)
- suitable for embedding: it depends on the size of the function, the frequency of the function call, the gain through the built-in and optimization settings (speed and size of the code). Often tiny functions have the greatest benefits, but a huge function can be built in if it is called only once.
- built-in call depths and recursion settings
The third is probably the core of your question, but it really is a "specific heuristic for the compiler" - you need to check the compiler documents, but usually they do not give much guarantees. MSDN has some (limited) information for MSVC.
Besides trivialities (e.g. simple getters and very primitive functions), embedding as such is not very useful anymore. The call instruction cost has decreased, and branch prediction has improved significantly.
A great nesting opportunity is to remove code paths that the compiler knows will not be taken - as an extreme example:
inline int Foo(bool refresh = false) { if (refresh) {
A good compiler will be built in Foo(false) , but not Foo(true) .
When generating the communication time code, Foo can be in .cpp (without an inline declaration), and Foo(false) will still be embedded, so again the built-in has only minor effects.
To summarize: There are several scenarios in which you should try to perform manual inlining control by placing (or excluding) the built-in statements.
peterchen
source share