Question Details

No question body available.

Tags

c thread-safety atomic compiler-optimization memory-barriers

Answers (2)

Accepted Answer Available
Accepted Answer
February 10, 2026 Score: 6 Rep: 27,489 Quality: Expert Completeness: 50%

The ISO C standard already allows compilers to "downgrade" a seq_cst to relaxed if it determines that this will not change the observable behavior of the program.

However, compilers generally perform optimizations on a per-thread basis, because they are generally unaware of what the other threads are doing. This means that a compiler is generally unable to make the determination whether such a "downgrade" will change the observable behavior of the program. So compilers are generally unable to perform such an optimization.

It is possible that compilers may become much smarter in the future, so that inter-thread optimizations may become common. Until then, compilers will be relying on the programmer telling them which memory ordering is required.

February 11, 2026 Score: 3 Rep: 379,322 Quality: Medium Completeness: 80%

Never going to happen in practice.

Downgrading would require very hard whole-program optimization that's only plausible for tiny simple programs. Would probably be very computationally intensive to look for even if it were something compilers attempted, and hard to prove it was correct. (Memory ordering is a difficult topic. Compiler transformations that could potentially introduce threading bugs would be extremely hard to debug if they ever got anything wrong, harder than the usual case of local optimization on a per-function basis.)

And in practice not even plausible for any objects that might be globally-visible and thus touched by code in another library whose code isn't visible to the optimizer, which is a total showstopper for almost every real-world project.

Moreover, there are definitely cases where weaker memoryorder could allow executions that would be impossible with seqcst, but which the programmer wants to allow because they aren't actually a correctness problem. A compiler can't possibly know when that's ok if it ever changes the order of I/O or volatile operations, or the data used. (And more realistically, proving that nothing weird happens with acq/rel or relaxed instead of seqcst would be extremely hard, even if they could see the whole program and attempt inter-thread analysis in the first place.)


In practice compilers don't optimize atomics at all, basically treating them like volatile Atomic (Why don't compilers merge redundant std::atomic writes? - That won't change until we find a way to signal to the compiler when it would be ok vs. not ok. One example is sinking relaxed progress-bar-update stores out of a loop and doing one at the end.)

Currently, compilers just use recipes that are known to work for every possible context. (https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html). On ISAs where an operation requires the same barrier before and after, eliminating duplicate barriers for two ops in a row is the most you can hope for. (Like ARMv7 dmb ish before/after SC stores, so two SC stores in a row results in back-to-back dmb ish. Clang folds the duplicate dmb ish instructions down to 1, current nightly GCC still just blindly expands the recipe and has two back-to-back barriers: Godbolt)