alar ([info]nealar) wrote,
@ 2009-05-22 07:44:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Current mood: shocked
Current music:Venetian Snares - Hospitality

GCC vs AVR = 1:0
GCC - хороший компилятор. Но иногда его зарубает: в коде

uint16_t x;
int16_t ref;
uint32_t result;

result += (x-ref)*(x-ref);
он делает всё правильно, за исключением:
1. результат умножения должен быть 32битным
2. надо пользоваться командой перемножения знаковых чисел.
Причём, получить от него 32битный результат, немного пошаманив, можно. Но при этом пациент пытается перемножать 32битные числа! Добиться от него использования команды знакового умножения так и не удалось.

А вот оптимизатор у него - очень качественный: выделение подвыражений (в этом примере x-ref он считает 1 раз), размещение данных в регистрах, толковый пролог у функций и прерываний (я иногда на асме пишу хуже :)).




(31 comments) - (Post a new comment)


[info]iakovz
2009-05-22 04:50 am UTC (link)
очень качественный: выделение подвыражений (в этом примере x-ref он считает 1 раз), размещение данных в регистрах

тоже мне критерий "качественности" оптимизации ;-)

(Reply to this) (Thread)


[info]nealar
2009-05-22 04:59 am UTC (link)
А что - критерий качественности?

С оптимизатором тут пришлось повоевать. Потому что, если код написать вот как тут, в виде 4 строчек, то он просекал, что везде константы, и писал в бинарник пустоту. :)

(Reply to this) (Parent)(Thread)


[info]iakovz
2009-05-22 05:15 am UTC (link)
А что - критерий качественности?

ну, там не знаю, напр., что б MAC распознавал вместо создания отдельных инструкций и т.п. :-)

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 05:27 am UTC (link)
В данной ATMega нету MAC. Интересно, компиляторы для x86 распознают FSINCOS? ;)

(Reply to this) (Parent)(Thread)


[info]kashnikov
2009-05-22 06:43 am UTC (link)
А то!
http://technostuff.blogspot.com/2005/12/some-optimization-flags-on-gcc.html

На самом деле лучше лист почитать, а еще лучше исходнички ;-)

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 06:47 am UTC (link)
Какой лист?
BTW: вроде бы, FSINCOS не с пентиумов, а с 387 пошёл.

(Reply to this) (Parent)(Thread)


[info]kashnikov
2009-05-22 06:52 am UTC (link)
gcc-maintainers list

BTW: Да с 387. А в чём вопрос? :-)

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 06:54 am UTC (link)
По ссылке написано, что с пентиумов.

(Reply to this) (Parent)


[info]nealar
2009-05-22 09:12 am UTC (link)
Раз он такой умный, может, он и FLDPI знает? :)

(Reply to this) (Parent)


[info]nealar
2009-05-22 06:47 am UTC (link)
Исходничками GCC меня недавно пугали.

(Reply to this) (Parent)(Thread)


[info]iakovz
2009-05-22 12:04 pm UTC (link)
а я тут смотрю скоро захерять GCC.. вона Apple ставит на LLVM+Clang'и всякие.. и пусть! ;-)

(Reply to this) (Parent)(Thread)


[info]gremlinable
2009-05-23 07:36 pm UTC (link)
Угу... И FreeBSD, кстати, тоже =)
http://www.opennet.ru/opennews/art.shtml?num=21651

(Reply to this) (Parent)


[info]iakovz
2009-05-22 12:03 pm UTC (link)
нету MAC

я для примера привел че на память пришло..

(Reply to this) (Parent)


[info]nealar
2009-05-22 05:35 am UTC (link)
Копался тут с одним телемеханическим протоколам, встретил совершенно убойную весчь для оптимизаторов:
"если число установленных битов в байте - чётное, то" и сишный код
for(bitno=0,acc=0;bitno<8;bitno++)
{acc = acc ^ (tmp &1);
tmp = tmp >> 1;}
if(acc) {

На x86 это должно быть:
or tmp,tmp
jp

Не знаю, как это выглядит на Мотороле 68xxx, где этот протокол крутится.

(Reply to this) (Parent)


[info]kashnikov
2009-05-22 04:58 am UTC (link)
Какая там версия gcc? Как шаманили? :)

(Reply to this) (Thread)


[info]nealar
2009-05-22 05:03 am UTC (link)
Про версию выясню попозже. А шаманили примерно так:
uint16_t x;
int16_t ref;
uint32_t result;

int32_t tmp = x - ref;
result += tmp* tmp;

tmp нельзя объявить 16ибитным, потому что тогда (tmp*tmp) у пациента тоже получается 16ибитным.

(Reply to this) (Parent)(Thread)


[info]kashnikov
2009-05-22 06:46 am UTC (link)
Я думал компилятор шаманили :)

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 06:53 am UTC (link)
Компилятор трогать страшно. Да и невыгодно: если ради каждого проекта надо править компилятор, то проще просто на асме всё писать.

(Reply to this) (Parent)


[info]andy128k
2009-05-22 07:27 am UTC (link)
Вам бы неплохо было прочитать стандарт С.

6.3.1.8 Usual arithmetic conversions

1 Many operators that expect operands of arithmetic type cause conversions and yield result
types in a similar way. The purpose is to determine a common real type for the operands
and result. For the specified operands, each operand is converted, without change of type
domain, to a type whose corresponding real type is the common real type. Unless
explicitly stated otherwise, the common real type is also the corresponding real type of
the result, whose type domain is the type domain of the operands if they are the same,
and complex otherwise...

(Reply to this) (Thread)


[info]nealar
2009-05-22 07:42 am UTC (link)
common real type for the operands and result
Значит, С - не "кроссплатформенный ассемблер" :(
Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result
Вот тут, получается, GCC нарушает: вместо того, чтоб скастовать int16_t к типу результата, перемножает в 16 битах, а потом кастует результат к uint32_t. Или это у меня что-то с пониманием языка?

(Reply to this) (Parent)(Thread)


[info]andy128k
2009-05-22 08:55 am UTC (link)
Попросту говоря, результат умножения двух 16-ти битных целых -- 16-ти битное целое. Чтобы получить 32-ух битное число нужно чтобы хотя бы один из операндов был 32-ух битный.

Вы переносите опыт ассемблера на C. И этот опыт сыграл с вами злую шутку.

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 09:05 am UTC (link)
Это понятно. Хоть и непонятно, зачем такое надо было придумывать. Неясно, почему "общий тип операндов и результата" определяется тут не по результату.

(Reply to this) (Parent)(Thread)


[info]andy128k
2009-05-22 09:37 am UTC (link)
Потому, что разрядность результата всегда больше чем разрядность операндов. Это приведёт к тому, что придётся везде использовать максимальную разрядность.

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 10:51 am UTC (link)
и?

(Reply to this) (Parent)(Thread)


[info]andy128k
2009-05-22 11:08 am UTC (link)
Результат сложения двух 16-ти битных чисел -- 17-ти битное число. Скорее всего будет взято ближайшее, т. е. 32 бита. Сложение двух 32-ух битных даёт 33 бита (64).

int16 a;
int16 b;
int16 c;
...
a + b; /* здесь результат 32 бита */
a + b + с; /* а здесь уже 64. сюрприз? */

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 11:23 am UTC (link)
Не, со сложением неприкольно. А вот результат перемножения 16ибитных чисел - 32битное. К тому же, я вовсе не об этом.
int16 a,b,c;
int32 d;

d = a+b+c+c+c+a; // выводим тип: 16~16~a, a~16~b, b~16~c, c~16~d, d~16~32.

Варианта вижу ровно 2:
либо d = 32, как максимум из ширины результата и второго аргумента -> кастуем всё к int32 и складываем
либо (как в GCC) на тип результата забиваем, тогда a = 16 -> складываем всё, а потом кастуем результат к int32

(Reply to this) (Parent)(Thread)


[info]andy128k
2009-05-22 11:30 am UTC (link)
То есть то о чём я говорил выше. Пришли к тому, что разрядность максимальна. Какой теперь прок от 16-ти разрядных чисел?

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 12:26 pm UTC (link)
Мне тоже интересно, какой толк от шестнадцатибитного умножения, если результат кладут в 32 бита.

(Reply to this) (Parent)(Thread)


[info]_asl_
2009-05-22 12:53 pm UTC (link)
Потому что bitwidth extension, как правило, гораздо дешевле чем арифметическая операция большей разрядности. Представьте себе, что у Вас нет 32-битного умножения. Совсем.

(Reply to this) (Parent)(Thread)


[info]nealar
2009-05-22 01:54 pm UTC (link)
Пишется библиотечка и -вуаля- оно снова есть.
Расширения таки дешевле (одна или две команды), но. Мы намеренно теряем биты результата, а потом на место этих битов намеренно добиваем 0 или -1.
AVR - восьмибитный.

(Reply to this) (Parent)


[info]zabivator
2009-05-22 08:15 pm UTC (link)
Вообще, я лично щитаю что за llvm будущее.

Ребята пошли очень правильным путём - разработали унифицированное аппартно-независимое IR - при этом они позволили его легко генерить (трёхадресный код) делать JIT, и наконец-то решили мучавшую меня последние лет пять проблему "не сделаешь никакой язык - умрёшь писать кодогенератор".
Делали мы прототипчик на llvm. Вычисление выражения (a+b)/c - где a,b,c - decimal. Соревновались паттерн интерпретатор из двух функций, захаркоженная функция, вычисляющая данную формулу и llvm-jit комплируема функция.
Вычисляли мы эту хрень на SQL запросе, порядка миллиона строк, что ли. (decimal очень увесистый тип - 40 значащих BCD-чисел - т.е. 20 знаков + обработка всяких там переполнений).
Время компиляции llvm'а оказалось миллисекунды, interpretator показал 400 секунд, а захардкоженная версия + llvm одинаковое время - 299 секунд.
Отсюда вывод: оптимизит число-дробилки и инлайн llvm не хуже студии.

Да и вокруг такого стандартного IR два пальца об асфальт дружить любой язык с любой железякой.
Вот, как-то так.

(Reply to this)


(31 comments) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…