Ключики компилятора avr-gcc для уменьшения бинарника

AVR
Смысл в том, что те функции которые не вызываются, не включаются в исходный бинарник.
Добавляем в свой makefile строчки для компилятора -ffunction-sections и -fdata-sections
makefile + -ffunction-sections и -fdata-sections

Добавляем -Wl,-gc-sections для линкера:
makefile + -Wl,-gc-sections

Проверка:

Простенькая прога с функцией, -gc-sections пока закомментил.
Откомпилил:
-gc-sections закомментил

Раскомментил -gc-sections, откомпилил:
Раскомментил -gc-sections

Добавил вторую функцию, -gc-sections пока закомментил.
Откомпилил:
Две функции, -gc-sections закомментил

Раскомментил -gc-sections, откомпилил:
Две функции, раскомментил -gc-sections

Собственно исходники:
Gdocs

Оригинал моего коммента, годичной давности.
  • +2
  • 04 декабря 2011, 02:45
  • hexanaft

Комментарии (15)

RSS свернуть / развернуть
А за счёт чего получается выигрыш?
0
«Умная линковка» — линкер выкидывает неиспользуемые функции. В GCC+BinUtils это работает только через костыли. Особо это заметно в FreePascal, там вообще для смартлинковки приходится компилировать каждую функцию в отдельный объектный файл.
Здесь, судя по всему, каждая функция пихается в отдельную секцию, а линкер выкидывает неиспользуемые секции.
0
Именно так и делается. То есть если даже компилятору не скармливать опции, а все функции разнести по своим фалам (один файл — одна функция), а линкеру включить сборщика неиспользуемых секций — результат будет такой же.
0
GCC собирает пухлый бинарник? Хватит это терпеть!
0
Нас заставили так жить!
0
Кто подскажит, посмотрел листинг avr-gcc? фукнция

udd_control_in_set_NACK0();

объявленная

#define udd_control_in_set_NACK0() LASR16(&udd_sram.ep_ctrl[1].STATUS,USB_EP_BUSNACK0_bm)

#define LASR16(addr,msk) (*addr |= msk)

в листинге транслируется вот так

udd_control_in_set_NACK0();
15a2: e0 e3 ldi r30, 0x30; 48
15a4: f6 e2 ldi r31, 0x26; 38
15a6: 02 e0 ldi r16, 0x02; 2
15a8: 05 93 .word 0x9305; ????

а что такое .word 0x9305? GCC скомпилировал сам не знает что?
0
  • avatar
  • GIgor
  • 05 декабря 2011, 11:01
.word и собратья используются для размещения констант в области кода.
0
Я знаю зачем .word и собратья, я не понимаю почему она применена здесь. Я не понимаю почему одна часть gcc не знает что делает другая. Код word 9305, это команда LAS Z,R16 но листинг об этом не знает…
0
У gcc есть такой полезный ключик как -Os aka optimize for size. При этом компилятор предпочитает экономить на размере кода, даже если это может пойти в ущерб скорости его работы (например, не будет делаться разворачивание циклов и подобные оптимизации где бОльшая скорость достигается за счет увеличения размера кода).

Проблема только в том что я не вижу ни звука про этот вполне типичный ключик gcc в этой статье. А название статьи вроде бы к тому обязывает…
0
Честно говоря, про это я думал как само собой разумеющееся.
И, кстати, -Os не всегда дает меньший результат чем -O2, так как -Os выключает многие оптимизаторские возможности компилятора. И при разном стиле кода, результат может весьма различаться.

С "-gc-sections" фишка в другом, если функция не используется, то как ты ее не оптимизирую в 0 она все равно не превратится, и будет занимать место в исходном бинарнике. И к тому же "-gc-sections" ключик не компилятора, а линкера. (Правда без ключиков компилятора -ffunction-sections и -fdata-sections он работать не будет)

З.Ы. По оптимизации для AVR, есть вообще люто бешенный ключик компилятора "--combine -fwhole-program" который компилит все исходники в один объектник, а потом уже линкует, с оптимизацией, из него бинарник.
0
Честно говоря, про это я думал как само собой разумеющееся.
Для тех кто о них знает — да, а для тех кто gcc только-только увидел — не очень :)

И, кстати, -Os не всегда дает меньший результат чем -O2, так как -Os выключает многие оптимизаторские возможности компилятора. И при разном стиле кода, результат может весьма различаться.
Да. А на десктопе к тому же бывает что -Os быстрее -O2, за счет более частого попадания в кэш. К AVR конечно не относится, но в порядке курьеза из жизни компилеров — весьма даже неординарный факт. Оказывается лучше отмотать jmp-ы в кеше чем без них, но зато мимо кеша. Правда это актуально только для тех у кого кеш есть (т.е. это не AVR).

З.Ы. По оптимизации для AVR, есть вообще люто бешенный ключик компилятора "--combine -fwhole-program"
Вообще, он не только для AVR есть, но и для еще кучи всего под чего есть gcc, от Linux на MIPS до 64-битных бинарей виндовса, потому как gcc довольно универсальная штукенция. Ну да это все лирика, а вот описание всех потенциально полезных ключиков касающихся размера, собранных в одном месте и желательно с описаниями «а зачем мы это крутим и что оно делает?» — было бы более чем здорово (а совсем круто — с описанием возможных грабель, но это уж как повезет).
0
По поводу в одном месте, есть одно официальное место по ключикам оптимизации gcc, но там все не на русском, и довольно размытые формулировки встречаются, над которыми можно немало времени поломать голову. И провести много познавательных вечеров раскуривая все это дело =).
А вот ключики для AVR, в частности.
0
мой конфиг с которого я выжал все что можно было для оптимизации на производительность и размер (gcc 4.5 минимум):
gitorious.org/akatlib/akatlib/blobs/master/benchmark/Makefile
0
Ты его улчше текстом опиши. Какие опции, для чего и все такое.
+1
Настраивал свой Elcipse Indigo под такое поведение.

Может кому полезно будет, ибо непрозрачно с первого раза было.
Make файл там самогенерируется на основании свойств проекта, и править его руками не вариант.

Заходим в свойства проекта:
Для "-ffunction-sections и -fdata-sections":
Menu: Project->Properties->C/C++ Build->Settings->AVR Compiler->Optimization:
включить галки на
Each function in its own section (-ffunction-sections)
Each data item in its own section (-fdata-sections)

Для "-Wl,-gc-sections":
У линкера галки нет, поэтому руками в доп параметры:
Menu: Project->Properties->C/C++ Build->Settings->AVR Linker->General:
в поле «Other Arguments» пишем -Wl,-gc-sections


В итоге на проекте с Мегой16 и несколькими библиотеками ходящими из проекта в проект, где много функций написаны про запас и для отладки, получил уменьшение с 12668 байт до примерно 6200 байт кода прошивки.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.