7

If I declare an atomic variable, which is only used in a single thread, are compilers able to optimize that out, and replace std::atomic<T> with T in some cases?

I've read some articles about the compiler optimizations of atimics, but they are mostly about reordering and grouping locks and stores, not about eliminating them.

Let's take std:shared_pointer for example. It has an atomic counter, but if only a single thread can access it, it could be replaced with a simple counter, and it would still behave as if it would be an atomic.

Iter Ator
  • 8,226
  • 20
  • 73
  • 164
  • Relevant: https://stackoverflow.com/questions/15718262/what-exactly-is-the-as-if-rule – Passer By Jun 16 '18 at 11:47
  • depends on the situation and on how crappy the compiler. but usually, since "atomic" in many cases implies "volatile", so no. – David Haim Jun 16 '18 at 11:47
  • In this case, sometimes: https://godbolt.org/g/64o5v3 - I have not found an *interesting* case yet (certainly not something as complex as shared_ptr) – harold Jun 16 '18 at 12:26
  • 2
    @david: there is no link between atomic and volotile, except for the misuse in the past – JVApen Jun 19 '18 at 06:26
  • @JVApen No link as in an atomic access isn't a volatile access, but there is a lot of overlap in practice. Notably consume semantic is volatile semantic (almost). – curiousguy Jun 24 '18 at 17:04
  • Do you mean local optimization or global program analysis? – curiousguy Jun 24 '18 at 17:26

1 Answers1

1

The answer depends on what you assume as optimizing out atomics. Using atomics has 2 effects: enforcing the observable order of the statements and ensuring the processor caches get invalidated.

If you are using the Intel processors, most of the later can be simply removed. This because the processor guarantees the same behavior and no specific handling needs to be done.

However for the ordering, there is a different story. To eliminate the ordering constraints, your compiler should be able to prove that that you don't have a different observable behavior.

In practice, if you ever pass the pointer or the reference to a function in a different compilation unit, the compiler is unable to do the optimization. On the other end, if the compiler has full visibility on the usage, it could conclude that the memory barriers ain't needed and based on that eliminate them.

Solving the problem of the codegen is the easy problem to solve and to my awareness most industry compilers have at least some support for this. Eliminating the memory barriers on the other end is part of outgoing research, so you this might not be available or might only cover the very simple cases.

As you are asking about this, it might sound reasonable to think you know better for your use cases. However, I would advise to keep the atomics when you need atomic behavior. It is very time consuming to optimize this by hand, while the benefits might not be noticeable.

JVApen
  • 11,008
  • 5
  • 31
  • 67