Почему компилятор не оптимизирует код прерывания?
Недавно я столкнулся с проблемой изменения переменной только в обработчике прерываний. Сама переменная не была объявлена как volatile, поэтому на более высоких уровнях оптимизации компилятор нарушал код. Тем не менее, компилятор достаточно умен, чтобы скомпилировать код прерывания, потому что прерывание все еще срабатывает.
Итак, вот мои вопросы:
Если компилятор достаточно умен, чтобы скомпилировать код прерывания, почему он не достаточно умен, чтобы понять, что переменные изменяются внутри этого прерывания?
На более высоких уровнях оптимизации функции, которые не вызываются, оптимизируются. Поскольку никакой код не вызывает обработчик прерываний, он должен быть оптимизирован. Что заставляет компилятор компилировать код прерывания?
1 ответ
Модель языкового исполнения говорит, что обычная (энергонезависимая) переменная не может быть изменена "внешними силами". Т.е. если ваш поток кода явно не изменяет переменную, то с точки зрения этого потока кода переменная не может измениться. (Кроме того, что определено в C11 для многопоточного исполнения). Вы должны вручную "назначить" переменные, которые могут быть изменены обработчиками прерываний.
Это один из основных факторов, обеспечивающих эффективную оптимизацию кода Си. Его нельзя устранить, не оказав существенного негативного влияния на производительность программ на Си.
Во-первых, компиляторы обычно не оптимизируют удаленные функции с помощью внешних связей. Ваш обработчик прерываний объявлен с внешней связью?
Во-вторых, решение об оптимизации функции или ее сохранении на самом деле не зависит от того, вызывается функция или нет. Он основан на том, есть ли в вашей программе ссылка на соответствующий символ. Символы, на которые нет ссылок, удаляются, а символы, на которые они ссылаются, сохраняются. Есть и другие способы ссылки на символ функции, кроме его вызова. Например, получение адреса функции также считается ссылкой на символ функции. Функции, адреса которых взяты в любом месте программы, никогда не оптимизируются.
Ваша запись вектора прерывания каким-то образом инициализируется при запуске программы, что обычно включает получение адреса функции-обработчика. Этого уже достаточно, чтобы защитить эту функцию от оптимизации.