Тут вот какое дело: у компилятора задача, сделать "побочный эффект" выполнения программы таким, каким его делает исходный код. И для этой задачи все средства хороши. Вплоть до замены всей программы выводом единственной константы, если всё выполнение сводится лишь к этому.
Компилятору нужно вырезать, удалить всё лишнее. И если в ходе прогона программы на этапе компиляции, выяснится, что результат предопределён, то код вычислений будет выкинут, и на выход просто прогрузится константа.
Задача программиста - указать компилятору, что вот этот источник данных - изменчивый, не подразумевай, что его значение прежнее, а при обращении принудительно вычитай откуда указано - значение могло измениться.
P.S. Насчёт out-of-order execution. Если это выгодно с точки зрения использования кэша, выгодно с точки зрения переиспользования значений регистров (указателей), то порядок может быть изменён произвольно. При работе с периферией спасает лишь то, что переменные на адресах периферии объявлены как volatile.