https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78940
Bug ID: 78940 Summary: [missed optimization] Useless guard variable in thread_local defaulted constructor Product: gcc Version: 6.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: a...@cloudius-systems.com Target Milestone: --- If I write extern thread_local std::atomic<int> foo; gcc will emit guard variables everywhere to ensure it is properly constructed before use. The workaround is to wrap foo in an inline function, so the compiler can see its definition. That doesn't work when the constructor is defaulted: //////////// begin example //////////////// // following libstdc++ std::atomic template <typename T> struct my_atomic { T n; my_atomic() = default; explicit constexpr my_atomic(T n) : n(n) {} T load() const { return n; } }; inline my_atomic<int>& a1() { static thread_local my_atomic<int> v; return v; } inline my_atomic<int>& a2() { static thread_local my_atomic<int> v{0}; return v; } int foo() { return a1().load() + a2().load(); } //////////////// end example ////////////////////// This compiles to 0000000000000000 <foo()>: 0: 64 80 3c 25 00 00 00 cmpb $0x0,%fs:0x0 7: 00 00 4: R_X86_64_TPOFF32 guard variable for a1()::v 9: 75 09 jne 14 <foo()+0x14> b: 64 c6 04 25 00 00 00 movb $0x1,%fs:0x0 12: 00 01 f: R_X86_64_TPOFF32 guard variable for a1()::v 14: 64 8b 04 25 00 00 00 mov %fs:0x0,%eax 1b: 00 18: R_X86_64_TPOFF32 a2()::v 1c: 64 03 04 25 00 00 00 add %fs:0x0,%eax 23: 00 20: R_X86_64_TPOFF32 a1()::v 24: c3 retq The test for "guard variable for a1()::v" is clearly useless, since no initialization of a1()::v takes place. gcc correctly omits the guard variable for a2()::v.