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

Добавляем в свой makefile строчки для компилятора -ffunction-sections и -fdata-sections

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

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

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

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

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

Собственно исходники:
Gdocs
Оригинал моего коммента, годичной давности.
- +2
- 04 декабря 2011, 02:45
- hexanaft
«Умная линковка» — линкер выкидывает неиспользуемые функции. В GCC+BinUtils это работает только через костыли. Особо это заметно в FreePascal, там вообще для смартлинковки приходится компилировать каждую функцию в отдельный объектный файл.
Здесь, судя по всему, каждая функция пихается в отдельную секцию, а линкер выкидывает неиспользуемые секции.
Здесь, судя по всему, каждая функция пихается в отдельную секцию, а линкер выкидывает неиспользуемые секции.
Кто подскажит, посмотрел листинг 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 скомпилировал сам не знает что?
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 скомпилировал сам не знает что?
У gcc есть такой полезный ключик как -Os aka optimize for size. При этом компилятор предпочитает экономить на размере кода, даже если это может пойти в ущерб скорости его работы (например, не будет делаться разворачивание циклов и подобные оптимизации где бОльшая скорость достигается за счет увеличения размера кода).
Проблема только в том что я не вижу ни звука про этот вполне типичный ключик gcc в этой статье. А название статьи вроде бы к тому обязывает…
Проблема только в том что я не вижу ни звука про этот вполне типичный ключик gcc в этой статье. А название статьи вроде бы к тому обязывает…
Честно говоря, про это я думал как само собой разумеющееся.
И, кстати, -Os не всегда дает меньший результат чем -O2, так как -Os выключает многие оптимизаторские возможности компилятора. И при разном стиле кода, результат может весьма различаться.
С "-gc-sections" фишка в другом, если функция не используется, то как ты ее не оптимизирую в 0 она все равно не превратится, и будет занимать место в исходном бинарнике. И к тому же "-gc-sections" ключик не компилятора, а линкера. (Правда без ключиков компилятора -ffunction-sections и -fdata-sections он работать не будет)
З.Ы. По оптимизации для AVR, есть вообще люто бешенный ключик компилятора "--combine -fwhole-program" который компилит все исходники в один объектник, а потом уже линкует, с оптимизацией, из него бинарник.
И, кстати, -Os не всегда дает меньший результат чем -O2, так как -Os выключает многие оптимизаторские возможности компилятора. И при разном стиле кода, результат может весьма различаться.
С "-gc-sections" фишка в другом, если функция не используется, то как ты ее не оптимизирую в 0 она все равно не превратится, и будет занимать место в исходном бинарнике. И к тому же "-gc-sections" ключик не компилятора, а линкера. (Правда без ключиков компилятора -ffunction-sections и -fdata-sections он работать не будет)
З.Ы. По оптимизации для AVR, есть вообще люто бешенный ключик компилятора "--combine -fwhole-program" который компилит все исходники в один объектник, а потом уже линкует, с оптимизацией, из него бинарник.
Честно говоря, про это я думал как само собой разумеющееся.Для тех кто о них знает — да, а для тех кто gcc только-только увидел — не очень :)
И, кстати, -Os не всегда дает меньший результат чем -O2, так как -Os выключает многие оптимизаторские возможности компилятора. И при разном стиле кода, результат может весьма различаться.Да. А на десктопе к тому же бывает что -Os быстрее -O2, за счет более частого попадания в кэш. К AVR конечно не относится, но в порядке курьеза из жизни компилеров — весьма даже неординарный факт. Оказывается лучше отмотать jmp-ы в кеше чем без них, но зато мимо кеша. Правда это актуально только для тех у кого кеш есть (т.е. это не AVR).
З.Ы. По оптимизации для AVR, есть вообще люто бешенный ключик компилятора "--combine -fwhole-program"Вообще, он не только для AVR есть, но и для еще кучи всего под чего есть gcc, от Linux на MIPS до 64-битных бинарей виндовса, потому как gcc довольно универсальная штукенция. Ну да это все лирика, а вот описание всех потенциально полезных ключиков касающихся размера, собранных в одном месте и желательно с описаниями «а зачем мы это крутим и что оно делает?» — было бы более чем здорово (а совсем круто — с описанием возможных грабель, но это уж как повезет).
По поводу в одном месте, есть одно официальное место по ключикам оптимизации gcc, но там все не на русском, и довольно размытые формулировки встречаются, над которыми можно немало времени поломать голову. И провести много познавательных вечеров раскуривая все это дело =).
А вот ключики для AVR, в частности.
А вот ключики для AVR, в частности.
мой конфиг с которого я выжал все что можно было для оптимизации на производительность и размер (gcc 4.5 минимум):
gitorious.org/akatlib/akatlib/blobs/master/benchmark/Makefile
gitorious.org/akatlib/akatlib/blobs/master/benchmark/Makefile
Настраивал свой 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 байт кода прошивки.
Может кому полезно будет, ибо непрозрачно с первого раза было.
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 байт кода прошивки.
- Alex_Ismagilov
- 05 июня 2014, 13:27
- ↓
Комментарии (15)
RSS свернуть / развернуть