Разрешено ли компилятору постоянно сворачивать локальную переменную?
Рассмотрим этот простой код:
void g();
void foo()
{
volatile bool x = false;
if (x)
g();
}
https://godbolt.org/z/I2kBY7
Вы можете видеть, что ни gcc
, ни clang
не оптимизируют потенциальный вызов g
. В моем понимании это правильно: абстрактная машина предполагает, что переменные volatile
могут изменяться в любой момент (например, из-за аппаратного отображения), поэтому постоянное свертывание инициализации false
в проверку if
будет неправильно.
Но MSVC полностью исключает обращение к g
(хотя чтение и запись в volatile
сохраняются!). Это стандартное поведение?
Background: I occasionally use this kind of construct to be able to turn on/off debugging output on-the-fly: The compiler has to always read the value from memory, so changing that variable/memory during debugging should modify the control flow accordingly. The MSVC output does re-read the value but ignores it (presumably due to constant folding and/or dead code elimination), which of course defeats my intentions here.
Редактирование:
Здесь обсуждается исключение операций чтения и записи в volatile
: Разрешено ли компилятору оптимизировать локальную изменчивую переменную? (спасибо Натану!). Я думаю, что стандарт совершенно ясен, что эти чтения и записи должны произойти. Но это обсуждение не охватывает вопрос о том, является ли законным компилятор принимать результаты этих чтений как должное и оптимизировать их на этом основании. Я предполагаю, что это under-/не указано в стандарте, но я был бы счастлив, если бы кто-то доказал, что я неправ.
Конечно, я могу сделать x
нелокальной переменной, чтобы обойти проблему. Этот вопрос больше из любопытства.
Ответы
Ответ 1
Я думаю, что [intro.execution] (номер параграфа может отличаться) можно использовать для объяснения поведения MSVC:
Экземпляр каждого объекта с автоматической продолжительностью хранения связан с каждой записью в его блоке. Такой объект существует и сохраняет свое последнее сохраненное значение во время выполнения блока и пока блок приостановлен...
Стандарт не разрешает исключение чтения через изменчивое значение, но параграф выше может быть интерпретирован как позволяющий предсказать значение false
.
Кстати, стандарт C (N1570 6.2.4/2) гласит, что
Объект существует, имеет постоянный адрес и сохраняет свое последнее сохраненное значение в течение всего срока его жизни. 34
34) В случае изменчивого объекта последнее хранилище не обязательно должно быть явным в программе.
Неясно, может ли быть неявное хранилище в объекте с автоматической продолжительностью хранения в памяти C/объектной модели.