Writes to volatile variables are somehow side effects in C++ and generally can't be optimized out under as-if rule, usually. In practice, this usually means that on inspection of the assembly you'll see one one store for each volatile store by the abstract machine1.
However, it isn't clear to me if the stores must be performed in the following case where the underlying object is not volatile, but the stores are done through a pointer-to-volatile:
void vtest() {
int buf[1];
volatile int * vptr = buf;
*vptr = 0;
*vptr = 1;
*vptr = 2;
}
Here, gcc does in fact optimize out all of the stores. Clang does not. Oddly, the behavior depends on the buffer size: with buf[3] gcc emits the stores, but with buf[4] it doesn't and so on.
Is gcc's behavior here legal?
[1] with some small variations, e.g., some compilers will use a single read-modify-write instruction on x86 to implement something like v++ where v is volatile).