1

as we know: load with memory_order_acquire, store with memory_order_release However, I found with gcc4.8.2, open -O2, a compile error throwed, /usr/include/c++/4.8.2/atomic:199:9: error: invalid memory model for '__atomic_store' but if close -O2, the error disappeared

further more, if with gcc8.3.0, the error would throwed even when with -O2

So what happend? how to explain this?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Chanjun
  • 13
  • 2
  • 1
    Can you give a specific example of code that fails? And does "open -O2" mean with the option, or without it? "Open/closed" isn't standard terminology for command line options. – Nate Eldredge May 21 '20 at 16:07
  • 1
    from [std::atomic::store](https://en.cppreference.com/w/cpp/atomic/atomic/store) - *order must be one of `memory_order_relaxed`, `memory_order_release` or `memory_order_seq_cst`. Otherwise the behavior is undefined.* if look for concrete lib implementation (i look for msvc not gcc) - [`_Check_store_memory_order`](https://github.com/microsoft/STL/blob/master/stl/inc/atomic#L151) and [store](https://github.com/microsoft/STL/blob/master/stl/inc/atomic#L419) - visible that `_INVALID_MEMORY_ORDER` case executed. which expand to nothing or to `_STL_REPORT_ERROR("Invalid memory order")` – RbMm May 21 '20 at 16:19
  • @Nate Eldredge open -O2 I mean with this option – Chanjun May 22 '20 at 15:57

1 Answers1

0

Without optimization, the order isn't visible as a compile-time constant to a compiler built-in, and GCC just treats runtime-variable orders as seq_cst (instead of branching on the value to skip an mfence). Optimization is required for constant-propagation to make the illegal order visible to the compiler logic that checks it, and give you the expected error.

std::atomic<T>::store() is a function written in C++ which takes an order arg and passes that variable to the GNU C builtin __atomic_store.

Without optimization, constant-propagation doesn't happen. Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?. Even __attribute__((always_inline)) doesn't make the compiler optimize when inlining, it just avoids having an actual function call. Why is this C++ wrapper class not being inlined away?

If you look at the resulting un-optimized asm, there's even a non-inlined call to std::operator&(std::memory_order, std::__memory_order_modifier) https://godbolt.org/z/dhViAG. But the atomic store itself inlined.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • thanks so much, but I can not understand "instead of branching on the value to skip an mfence", why gcc just treats runtime-variable orders as seq_cst? – Chanjun May 22 '20 at 15:56
  • 1
    @Chanjun: because `seq_cst` is always strong enough, and runtime-variable `order` is basically never used in source code. So this only happens with un-optimized code, and it's a simple way to make less bloated asm. It's not worth making the compiler more complicated to do anything else because it only affects un-optimized code, and un-optimized code doesn't matter. Stop wasting your time looking at it, unless you want to know about GCC internals. – Peter Cordes May 22 '20 at 16:01
  • GCC unoptimized code generated is often ugly, but with `std::atomic`, ouch. It's really ugly. – curiousguy May 22 '20 at 18:48
  • 1
    @curiousguy: templated C++ code is usually a nightmare without optimization. C11 `stdatomic` is IIRC not much worse than you'd expect most of the time. – Peter Cordes May 22 '20 at 18:50