QUOTE (Fat Robot @ Mar 2 2016, 14:53)

Скажите, есть ли у вас какие-то оценки результата сборки при переходе на gcc?
Как изменился footprint?
Да, конечно, это в первую очередь оценивалось, т.к. у меня ориентация на то, что программа должна помещаться во внутренней памяти программ. Общая оценка такая: front-end компилятора очень хорош, код общего назначения оптимизирует отлично - всё что можно "просчитать" на этапе сборки, он делает, в итоге код (тестовый) из нескольких вызовов (правда простых) функций с какой-то тупой логикой (ну, просто для теста там всякая бессмысленная арифметика делалась) в сгенерённом коде выливался всего в пару инструкций. Это поначалу вводило в подозрение - что это, де, за фигня, поди ошибка, но тщательный разбор показывал, что действительно это нагромождение кода по факту выливается в декремент на два, что в итоге компилятор и выдал.
Полагаю, это благодаря тому, что gcc front-end является весьма высококачественным и с точки зрения поддержки средств языка (С++), и с точки зрения оптимизации логики.
С кодогенератором тут похуже, всё-таки vdsp++ в этом смысле более доведён до ума. Но на коде общего назначения эта разница почти не сказывается, а DSP код, моё мнение, надо писать либо на ассемблере (при использовании обоих тулчейнов), либо использовать специализированные функции.
Конкретно на чём bfin-elf проигрывает vdsp++:
- использование аппаратных циклов;
- оптимизация конвейера;
Если vdsp++ втыкает lsetup(...) LCn = ... каждом случае, то bfin-elf это делает куда менее охотно даже при опции компилятора -funsafe-loop-optimizations. Какая логика им рулит, для меня пока осталось неясным. Конечно, аппаратный цикл чаще всего лучше, чем цикл с явным переходом по инструкции ветвления. Лучше и по производительности, и по размеру кода.
С конвейером vdsp++ производит очень жёсткие оптимизации - переставляет инструкции так, что там вручную понять, что к чему относится, всегда было непростой задачей, что очень затрудняло отладку по коду. Меня по началу это выводило, а потом когда я писал свой кусок на асме, то налетел на предупреждения о простаивании конвейера, дескать, из-за того, что вот загрузил адрес в P-регистр, и в следующей инструкции уже пытаюсь обращаться по нему, а адрес-то по конвейеру ещё не доехал до аппаратуры, которая осуществляет адресацию, поэтому конвейер stall 3 такта... Думаю, вот чего он будет простаивать, я пока что-то другое могу поделать... И тут замечаю, что я и сам начинаю вот точно так же переставлять инструкции в потоке. В общем, зауважал компилятор.
bfin-elf такой виртуозности не достиг, у него код более линейный, может он и переставляет там что-то, но я как-то не заметил - отладка кода куда проще - всё читается сходу. Что заметил у этого компилятора: он хорошо "держит" контекст, т.е. как бы "помнит" какие ресурсы он на что использовал и в каком они состоянии. Например, смотрю фрагмент кода (кода бился с этим гадким багом с порчей регистра в прерывании), вижу, там почему-то адрес массива не грузится в P-регистра, а делается операция декремента этого регистра на какое-то значение. Думаю, что это - баг, что-ли - прога-то вылетает, вот на любое место подозрение.
Стал разбираться, оказалось, что всё корректно: регистр был ранее загружен значением адреса, связанным с адресом упомянутого массива, и компилятор просто "помнит" это и "знает" эту связь, а получить нужное значение адреса выгоднее одной арифметической операцией с P-регистром, чем явно грузить половинки адреса - это две инструкции, и они, вдобавок, ещё и "толстые" - каждая тащит 16 бит значения адреса.
Т.е. нельзя сказать, что кодогенератор совсем уж тупой - вот такие вещи он делает очень прилично. Возможно, это связано с тем, что это оптимизации общего плана, и тут gcc уже не одну "собаку съел", а вот с вещами, "завязанными" на аппаратуру конкретного процессора (конвейер, аппаратные циклы) у него послабее.
По факту портировал два проекта, финальные размеры кода (в байтах):
CODE
Project# 1 2
vdsp++: 20288 66194
bfin-elf: 19748 67880
Очень сильно на это влияет качество библиотек. Первый проект, когда в первый раз запустил, размер кода был что-то под 45 килобайт! Я даже офигел поначалу. Потом стал смотреть в мапе, что же там столько жрёт. Оказалось это библиотека плавающей точки и библиотека форматированного вывода.
С плавающей точкой удалось разобраться относительно легко - оказалось, в составе bfin-elf есть та самая оптимизированная либа плавающей точки из vdsp++ (очень хорошая реализация), просто её надо было правильно подключить: там есть опция gcc "-mfast-fp", которая должна была бы это сделать, я её передал компилятору, и толку не было. А оказывается её надо линкеру передавать. Сам фронт-энд gcc, видимо, умеет правильно конфигурировать вызовы, но я сборку организую как раздельные вызовы компилятора, ассемблера, линкера, вот передавал не тому тулу. Это нигде не освещается, опция gcc и всё. Ошибочно полагал, что при этой опции компилятор будет генерировать другие имена библиотечных функций. Но нет, имена те же, просто линкер подсовывает другую либу, что, в общем, проще и логичнее. Только бы документировать этот момент почётче.
А та библиотека, которую он по умолчанию вставляет, это, по ходу, тянуто с РС, там всё очень неоптимально. Для сравнения: функция умножения плавающей точки имеет размер 1.7 кбайта в то время как оптимизированная библиотека эту же функцию реализует что-то в 270 байт. Вот так вот и разница набегает.
Оптимизированная либа не совсем полноценна - она не все требования стандарта выполняет (проверок на NaN нету, ещё что-то подобное), но для наших применений это, как правило, несущественно. Тем более, что на vdsp++ используется она же.
Форматированный вывод тоже достаточно безобразно сделан. Поэтому была подтянута сторонняя реализация - она есть в упомянутой в предыдущем посте библиотеке на гитхабе.
Ну, и во втором проекте используются немного контейнеры stl, что тянет за собой алокаторы, т.е. работу со свободной памятью. Реализация из bfin-elf тоже никакая, поэтому тоже была подтянута сторонняя библиотека.
В с этими либами результат такой, как показан выше. Собственно, идея с этой коллекцией библиотек отсюда и поизросла.
QUOTE (Fat Robot @ Mar 2 2016, 14:53)

Есть ли заметные изменения в производительности?
Явных тестбенчей не проводил, единственное, что замерял - это время передачи управления между процессами в scmRTOS, в случае vdsp++ оно было 1.5 мкс (200 МГц тактовая проца), на bfin-elf - 1.6 мкс. Т.е. чуть похуже, но не фатально.
В общем, мой вывод: несмотря на все трудности, жить можно, результат на bfin-elf не лучше, но и почти не хуже. Опасения за качество кодогенерации, можно сказать, не подтвердились. Больше всего напрягает то, что тулчейн, видимо, не развивается.
«Отыщи всему начало, и ты многое поймёшь» К. Прутков