With -flto, is manual inline unnecessary?


With LTO, it seems that compilers should have the information to
decide whether to inline a function or not. In this case, is it
unnecessary to specify functions as inline in C/C++ code?

The inline keyword is a hint. The inliner calculates the cost of inlining a function using various heuristics. If the cost is too high it won’t be inlined. The inline keyword increases the threshold that is considered too costly.

To follow on to Craig’s note about it being a hint, note that the inline keyword is largely there to adjust the linkage type of the symbol so that it can be defined in a header without getting multiply defined symbol errors, and to allow it to be elided by the compiler when it isn’t used in a translation unit that included that header. Without LTO, defining an inline function in a header can aid in inlining simply by making the definition available to all callers. But there is a cost (compile time, memory overhead) for defining a function in the header and therefore in all translation units that include it. With LTO (or ThinLTO), you can move these definitions to a source file (in which case the inline keyword must be removed), and it will still be available to inline as needed. LTO does this by merging all IR, which of course comes with a potentially big cost to memory and loss of incremental compiles. With ThinLTO (-flto=thin) the IR will be temporarily imported into other modules where it is thought to be profitable to inline.

To really force inlining, you would instead need to use the attribute “attribute((always_inline))”. However, with or without LTO, it is typically better to let the compiler use its heuristics to determine whether inlining is profitable.