This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/78940] New: [missed optimization] Useless guard variable in thread_local defaulted constructor
- From: "avi at cloudius-systems dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 28 Dec 2016 11:29:47 +0000
- Subject: [Bug c++/78940] New: [missed optimization] Useless guard variable in thread_local defaulted constructor
- Auto-submitted: auto-generated
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: avi@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.