Если я правильно понимаю то, что написано на cppreference, компилятор не может изменять порядок доступа к двум volatile, но может переставлять запись/чтение volatile и обычной переменной. cvВсе IO регистры и так объявлены volatile, а переменные, порядок доступа к которым важен, можно либо тоже сделать volatile, либо читать/писать специально обученными функциями, типа такого:
template <typename T>
inline T volatile_read(const T& x) { return *(const_cast<const volatile T*>(&x)); }
template <typename T>
inline void volatile_write(T& y, T x) { *(const_cast<volatile T*>(&y)) = x; }