https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122760
Bug ID: 122760
Summary: Missed optimization: constexpr std::atomic<int> x{0}
not constant-propagated through load()
Product: gcc
Version: 15.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: marc.mutz at hotmail dot com
Target Milestone: ---
I would expect a constexpr std::atomic's value to be constant-folded like
everything else, but it's not:
// https://godbolt.org/z/YaMn6x5GG
#include <atomic>
extern int foo();
constexpr std::atomic<int> call_foo{0};
int main() {
if (call_foo.load(std::memory_order_relaxed))
return foo();
return 0;
}
Clang optimizes this to "return 0", even in -O1. GCC, OTOH, emits a runtime
check, even at -O3, no matter whether I use load(memory_order_relaxed) or
implicit operator int().
This matters because a) Clang does it and b) we often have config variables
that are only needed in certain build types, but in the build types in which
they exist, they have to be atomic, if only relaxed, because tests set them in
the middle of the test, but you cannot be sure that there are no other threads
which are executing the code that reads them, causing data races. So I'd like
to make
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/text/qunicodetools.cpp?h=6.10.0#n20
L20-25 an atomic<int>, but then, when it's constexpr, it's still being checked,
even in optimized builds.
That said, you're in good company, as MSVC also doesn't optimize this, but
Clang shows it can be done.