http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56360
Bug #: 56360 Summary: Loop invariant motion can introduce speculative store Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassig...@gcc.gnu.org ReportedBy: i...@airs.com When I compile this C++ program with -O3 -std=gnu+11 on x86_64: #include<mutex> #include<thread> extern int a; std::mutex m; void nop2(int*); // this function is ONLY called with i=0. void foo(int i) { if (i) m.lock(); nop2(&i); // Only here to prevent optimiser from creating one big if(). for (int c = 0; c < 10000; ++c) { if (i) { ++a; // Thus this is never executed. } } nop2(&i); // Only here to prevent optimiser from creating one big if(). if (i) m.unlock(); } I see this in _Z3fooi: movl a(%rip), %eax movl 12(%rsp), %ecx leaq 12(%rsp), %rdi leal 10000(%rax), %edx testl %ecx, %ecx cmovne %edx, %eax movl %eax, a(%rip) This unconditionally stores a value in a. This is a speculative store, which is invalid according to the C++ memory model. This does not happen with -O2. >From looking at the dumps, the bug appears to be in the loop invariant motion pass.