I wrote in my previous post that I assumed Jason compiled using the
-O2
optimization level for the example in his CppCon 2016 talk, as it worked for me when I used -O3
. But I was wrong – Jason used -O3
, but his example was slightly different compared to mine. I used the functionint bar() { return std::string("a").size() + std::string("b").size(); }that optimizes to just returning a constant, while Jason used
int main() { return std::string("a").size() + std::string("b").size(); }which does not optimize. The only difference is the name of the function...
The reason for the difference is that GCC knows that
GCC is propagating the "called only once" information where possible, so functions for which the compiler can see all callers (such as
On the other hand, if the "called only once" function contains loops, then GCC can infer that it makes sense to optimize the content of the loop as it is executed multiple times. So for examplemain
is special — it has the property that it is called only once. That is, it is a cold function, which makes the inlining less aggressive.GCC is propagating the "called only once" information where possible, so functions for which the compiler can see all callers (such as
static
functions, functions in an anonymous namespace, or when compiling using -fwhole-program
) are also marked as "called only once" if they are called exactly once from such a function. For example, the compiler can see that bar
is called only once instatic int bar() { return std::string("a").size() + std::string("b").size(); } int main() { return bar(); }and the string code is not inlined. Removing
static
prevents GCC from marking bar
as called only once (as it could be called from outside the translation unit), and the string code will now be inlined.int main() { int k = 0; for (int i = 0; i < 10000; i++) k += std::string("a").size() + std::string("b").size(); return k; }gets the strings inlined, and it optimizes to
main: mov eax, 20000 ret