Разрешено ли компилятору постоянно сворачивать локальную переменную?

Рассмотрим этот простой код:

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 сохраняются!). Соответствует ли это стандартному поведению?


Предыстория: я иногда использую такую ​​конструкцию, чтобы иметь возможность включать / выключать отладочный вывод на лету: компилятор должен всегда читать значение из памяти, поэтому изменение этой переменной / памяти во время отладки должно соответствующим образом изменить поток управления. Выходные данные MSVC перечитывают значение, но игнорируют его (предположительно, из-за постоянного свертывания и / или удаления мертвого кода), что, конечно, противоречит моим намерениям.


Редактировать:

  • Здесь обсуждается исключение операций чтения и записи в volatile: Разрешено ли компилятору оптимизировать локальную энергозависимую переменную? (спасибо Натан! ). Я думаю, что стандарт совершенно ясен, что чтение и запись должны произойти . Но это обсуждение не охватывает вопрос о том, является ли законным компилятор принимать результаты этих чтений как должное и оптимизировать на их основе. Я предполагаю, что это недооценено / не указано в стандарте, но я был бы счастлив, если бы кто-то доказал мою неправоту.

  • Конечно, я могу сделать x нелокальной переменной, чтобы обойти проблему. Этот вопрос больше из любопытства.

19
задан Max Langhof 17 October 2019 в 07:45
поделиться

0 ответов

Я думаю [intro.execution] (номер абзаца варьируются), мог использоваться для объяснения поведения MSVC:

экземпляр каждого объекта с продолжительностью автоматического хранения связан с каждой записью в свой блок. Такой объект существует, и сохраняет его последнюю хранимую сумму во время выполнения блока и в то время как блок приостановлен...

стандарт не разрешает устранение чтения через энергозависимый glvalue, но абзац выше мог быть интерпретирован как позволяющий предсказывать значение false.

<час>

BTW, в Стандарте C (N1570 6.2.4/2) говорится, что

объект существует, имеет базовый адрес и сохраняет свою последнюю хранимую сумму в течение его времени жизни. <глоток> 34

<час>

34) В случае энергозависимого объекта, последнее хранилище не должно быть явным в программе.

неясно, могло ли быть неявное хранилище в объект с продолжительностью автоматического хранения в памяти/объектной модели C.

1
ответ дан Language Lawyer 21 October 2019 в 13:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: