News for hackers. Stuff that matters.
Re:No sane compiler would optimize atomics (2015) by gpderetta on Monday July 12, 2021 @04:50AM (#27808357)
volatile should work. Each volatile access is a side effect from the point of view of the abstract machine and compilers are supposed to document this mapping to the concrete CPU (and usually is the obvious one).

In fact the fact that volatile atomic has additional guarantees is a strong reason for plain atomic not to have them, otherwise there wouldn't be a way to express the more relaxed requirement.

I think atomic not being volatile by default is a good default: the majority of code doesn't need to care about atomic in the first place, for the majority of the remaining code, these sort of optimizations are benign and desirable. For the remaining code that cares, volatile is the safety hatch.

Re:No sane compiler would optimize atomics (2015) by dataflow on Monday July 12, 2021 @05:06AM (#27808436)
I'm not so sure volatile is sufficient... I expect it would depend at least on how the variable is allocated/stored. Merely putting volatile shouldn't be sufficient to prevent access to it being optimized out. I forget if this was disallowed since C++20, but consider the program 'int main() { volatile int x = 0; ++x; }'. I'm fairly certain the compiler can optimize out the body despite the use of volatile, because of the as-if rule: it would be impossible to tell the difference from within the program.

Moreover, I'm not sure 'volatile' memory access without some sort of external linkage is even meaningful. The idea of volatile is that access to a volatile variable could have observable side effects outside the program, but that discussion seems rather moot for a variable that doesn't have connections to the outside world to begin with. Heck, by the same reasoning, even for a variable with external linkage, the rules might still permit it to be optimized out under link-time optimization, unless it has been declared to be externally reachable somehow (e.g. at a fixed/exported/otherwise 'known' address)... otherwise it's by definition externally unreachable and thus again unobservable under the as-if rule.

At least, I could see the reasoning going that way, and that's how it makes sense to me as far as the abstract machine goes. I can also see people disputing it though, and claiming (say) a debugger inspecting a program is sufficient accessibility for considering side effects, or something like that. I'm not sure I agree with every objection, but I see room for debate. It's just not clear what the implications are under the as-if rule.

Re:No sane compiler would optimize atomics (2015) by gpderetta on Monday July 12, 2021 @05:34AM (#27808576)
The ++x is a side effect from the abstract machine point of view. The issue is of course how the compiler maps the abstract machine to the real machine. Volatile is (purposefully) underspecified and I guess it is not completely unreasonable for a compiler to declare that a local volatile object whose address is never taken does not have a mapping at all.

There is little value on explicitly optimizing volatiles but of course that can happen as a side effect (ah!) of unrelated optimizations.

I rarely use volatile at all, but when I do, I do make sure not to apply it to local objects.

edit: I think the most reliable and portable way to make sure that the address of a variable escapes is something like this:

   volatile std::atomic<void*> sink; // global

   void escape(void*x) { 
     std::atomic_signal_fence(std::memory_oreder_release);
     sink.store(x, std::memory_order_relaxed);
   }
any signal handler executed after escape(&val) is guaranteed to be able to see the last value stored into val.
Re:No sane compiler would optimize atomics (2015) by dataflow on Monday July 12, 2021 @06:49AM (#27808984)
Yeah, I think this is probably sufficient without whole-program optimization, but I'm not sure it is with LTO. It might be sufficient today, but I can imagine Clang optimizing it away eventually. Really, the only realistic-yet-futureproof method I can imagine (and I'm not sure if it's even within the jurisdiction of the language spec) is either (a) exporting the variable, or (b) exposing its address through some other established I/O mechanism (like printf).