gremlinable (gremlinable) wrote,
gremlinable
gremlinable

Category:

Оптимизация в GCC

Оптимизация глобальных переменных в GCC меня убивает. Хорошо известна фича, что если глобальная переменная изменяется в прерывании и считывается в основной программе, то компилятор может в целях оптимизации заменить эту переменную константой, после чего, разумеется программа становится неработоспособной. Решается этот вопрос с помощью модификатора volatile, который говорит компилятору, что данную переменную оптимизировать не надо.
Так вот, вчера убедился в том, что все новые грабли — это хорошо прикопанные старые. В целях оптимизации программы решил поместить пару часто используемых переменных в регистры, что бы значения не пересылались постоянно из памяти в регистр и обратно. Сказано — сделано: меняем

	volatile uint8_t  G_scheduler_reg1 = 0;
	volatile uint8_t  G_scheduler_reg2 = 0;

на

	register uint8_t  G_scheduler_reg1 asm("r3");
	register uint8_t  G_scheduler_reg2 asm("r4");

Компилится нормально, без ошибок и варнингов, экономия кода заметна невооружённым глазом. Только вот ассемблерник смущает — указанные регистры во многих местах используются не так, как я предполагал. Ну да ладно, списываю на компилятор — ему виднее, к тому же в доках написано, что даже если регистр указан явно, компилятор в некоторых случаях может использовать его по своему усмотрению.
В итоге приложение, конечно же, не заработало и долго я вкуривал в код, пока не вспомнил про пресловутый volatile (я допустил ещё одну серьёзную программерскую ошибку — между этой правкой и тестированием внёс в код ещё ряд изменений). Ну не думал я, что gcc и регистры ТАК оптимизирует. Кроме того, ещё одной причиной, по которой я не сразу сообразил в чём беда, было то, что эти переменные у меня используются и на чтение и на запись как в основной функции. так и в прерываниях, так что, вроде, заменять их на константы там негде.
Возвращение в объявление переменных злополучного модификатора volatile сразу программу починило. Но самое смешное в том, что итоговый файл стал меньше ещё на два байта по сравнению с вариантом без volatile =). (используется оптимизация -O2, так что, возможно, компилятор хотел сделать программу быстрее за счёт выбрасывания этих регистров)
Отсюда вывод — все глобальные переменные я теперь объявляю как volatile — может где-то что-то будет хуже соптимизированно, зато не надо будет долго искать аномальные косяки и непонятно откуда вылезшие подводные камни.
Tags: avr, gcc, программерское
Subscribe
  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 0 comments