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.

Reply via email to