"volatile semantics" aren't really correct here. This is what ReadNoFence() is for.
I was trying to argue for that, but realized that existing code isn't really conforming either. I'm not sure that volatile as a substitute for relaxed atomic access would be a problem in practice, but I do agree that atomic helpers are designed for this sort of thing.