реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> avr-libc и uint64_t арифметика, или баг, или я чего-то не понимаю...
ARV
сообщение Sep 28 2009, 16:46
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



Код
volatile uint64_t v1;
volatile uint32_t v2;

int main(void)
{
    v2 = v1/v2;
    PORTD = 12;
    while(1);
}
этот тривиальный код компилируется для attiny2313 в 3940 байтов flash и 278 байт ОЗУ!!!! это как такое называется?! при этом если обе переменные v1 и v2 сделать uint32_t, то размер кода становится практически в 20 раз меньше: 200 байт flash !!! что там такое в libc понаделано, что получается такое разрастание кода?! ведь если руками написать функцию деления "в столбик" - получится код значительно меньше...

P.S. разумеется, оптимизация -Os


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Lepeksiy
сообщение Sep 28 2009, 18:13
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 25-04-07
Пользователь №: 27 294



Ну дык никто не мешает посмотреть получившийся код...
Первое, что бросается в глаза - при 64 бит активно используется стек, в то время как при 32 бит обходится только регистрами. Плюс появляется множество ненужных пересылок. Вообще создалось впечатление, что тут "не ступала нога оптимизатора", несмотря на -Os.
Go to the top of the page
 
+Quote Post
ARV
сообщение Sep 28 2009, 18:48
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



я не вижу смысла смотреть в получающийся код - и так понятно, что там ужос... вопрос лишь в том, как это разработчики avr-libc такое допустили?! и каковы пути обхода проблемы?


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Goodefine
сообщение Sep 28 2009, 19:08
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Цитата(Lepeksiy @ Sep 28 2009, 21:13) *
.... создалось впечатление, что тут "не ступала нога оптимизатора", несмотря на -Os.

А чего ей там ступать, если все переменные volatile...


--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Sep 28 2009, 19:13
Сообщение #5


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



ARV, Вы полагаете, что разработчики где-то здесь, чтобы Вам ответить?
Или это просто так, чтобы повозмущаться?
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Sep 28 2009, 19:27
Сообщение #6


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Goodefine @ Sep 29 2009, 01:08) *
А чего ей там ступать, если все переменные volatile...

По аналогии все волатильные лонги тогда нужно перечитывать побайтно. Ведь в операции "v2 = v1/v2" и v1 и v2 считываются только 1 раз, а уж где их потом разместит компилятор - его личное дело, хоть в регистрах, хоть в стеке, но это месторасположение уже не будет волатильным. ИМХО - это недоработка оптимизации. Однозначно надо исправлять.

Цитата(ARV @ Sep 28 2009, 22:46) *
этот тривиальный код компилируется для attiny2313 в 3940 байтов flash и 278 байт ОЗУ!!!!

А в attiny2313 стока есть?

Сообщение отредактировал GetSmart - Sep 28 2009, 19:25


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Sep 28 2009, 20:52
Сообщение #7


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Там таки явно что-то не то.
Зачем-то большая таблица в ОЗУ
Код
00800060 <__clz_tab>:
  800060:    00 01           movw    r0, r0
  800062:    02 02           muls    r16, r18
  800064:    03 03           mulsu    r16, r19
  800066:    03 03           mulsu    r16, r19
  800068:    04 04           cpc    r0, r4
  80006a:    04 04           cpc    r0, r4
  80006c:    04 04           cpc    r0, r4
  80006e:    04 04           cpc    r0, r4
  800070:    05 05           cpc    r16, r5
  800072:    05 05           cpc    r16, r5
  800074:    05 05           cpc    r16, r5
  800076:    05 05           cpc    r16, r5
  800078:    05 05           cpc    r16, r5
  80007a:    05 05           cpc    r16, r5
  80007c:    05 05           cpc    r16, r5
  80007e:    05 05           cpc    r16, r5
  800080:    06 06           cpc    r0, r22
...
  80014c:    08 08           sbc    r0, r8
  80014e:    08 08           sbc    r0, r8
  800150:    08 08           sbc    r0, r8
  800152:    08 08           sbc    r0, r8
  800154:    08 08           sbc    r0, r8
  800156:    08 08           sbc    r0, r8
  800158:    08 08           sbc    r0, r8
  80015a:    08 08           sbc    r0, r8
  80015c:    08 08           sbc    r0, r8
  80015e:    08 08           sbc    r0, r8

и сам код деления какой-то странный, толи на С писанный, толи совсем непонятно что.
Надо исходники качнуть, глянуть.

upd: Фигушки, это не avr-libc надо смотреть, а libgcc

upd: оййо....
В общем исходнике на libgcc2.c , которій в зависимости от #defin-ов по разному работает и пітается типа оптимизировать скорость проверяя на 0-не0 старшие части и подвызывая другие функции (в комментариях что-то про встроенній асм, но я их вообще не нашёл).
Таблица в .data от того же исходника, она не используется, но и не выбрасывается даже по -Wl,-gc-sections, так как библиотека собрана без -fdata-sections


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ReAl
сообщение Sep 28 2009, 21:59
Сообщение #8


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(GetSmart @ Sep 28 2009, 22:27) *
ИМХО - это недоработка оптимизации. Однозначно надо исправлять.
Не оптимизации, а библиотеки поддержки. Её нужно "персонализировать" как-то. Может проще будет так, как с другими вещами сделано, многое в libm затолкано, которая из avr-libc - если её подключить, то размер кода уменьшается, так как берутся оптимизированные версии оттуда.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
singlskv
сообщение Sep 28 2009, 22:53
Сообщение #9


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(ReAl @ Sep 29 2009, 00:52) *
upd: оййо....
В общем исходнике на libgcc2.c , которій в зависимости от #defin-ов по разному работает и пітается типа оптимизировать скорость проверяя на 0-не0 старшие части и подвызывая другие функции (в комментариях что-то про встроенній асм, но я их вообще не нашёл).

Там все сводится к функции __udivmodsi4 (деление 32бит/32бит) которая для AVR в файле gcc/config/avr/libgcc.S ,
и __udivmodsi4 написана вполне прилично,
а вот то что в libgcc2.c это конечно кошмар кошмар
Go to the top of the page
 
+Quote Post
ARV
сообщение Sep 29 2009, 04:31
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



Цитата(IgorKossak @ Sep 28 2009, 23:13) *
ARV, Вы полагаете, что разработчики где-то здесь, чтобы Вам ответить?
Или это просто так, чтобы повозмущаться?
слабость знания английского не позволяет мне запостить вопрос в ином месте...
здесь время от времени появляется Aesok, которого я причислил к лику разработчиков smile.gif во всяком случае он не раз давал советы/ответы из самых глубин GCC - на него надеюсь и уповаю smile.gif

кстати, -lm не помогает уменьшить размер кода.

Цитата(GetSmart)
А в attiny2313 стока есть?
в тини стока нет, но компилятору-то по барабану smile.gif да и не в тини дело - для меги такой код тоже великоват как-то...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Sep 29 2009, 04:39
Сообщение #11


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



учитывая то, что мне часто нужны быстрые умножения 16*16=32, перестал морочить голову, завел файл с асмовыми вставками. Теперь там будут и для 64 битных. Тут уже по две версии - регистровая и через указатели.
Go to the top of the page
 
+Quote Post
klen
сообщение Oct 1 2009, 18:00
Сообщение #12


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



скомпилял этот пример

вот что получилось для -Os -mmcu=atmega64
Цитата
.file "int64.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
.global __do_copy_data
.global __do_clear_bss
.text
.global main
.type main, @function
main:
push r2
push r3
push r4
push r5
push r6
push r7
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push r16
push r17
/* prologue: function */
/* frame size = 0 */
lds r18,v1
lds r19,v1+1
lds r20,v1+2
lds r21,v1+3
lds r22,v1+4
lds r23,v1+5
lds r24,v1+6
lds r25,v1+7
lds r2,v2
lds r3,(v2)+1
lds r4,(v2)+2
lds r5,(v2)+3
movw r10,r2
movw r12,r4
clr r14
clr r15
ldi r16,lo8(0)
ldi r17,lo8(0)
call __udivdi3
movw r24,r18
movw r26,r20
sts v2,r24
sts (v2)+1,r25
sts (v2)+2,r26
sts (v2)+3,r27
ldi r24,lo8(12)
out 50-0x20,r24
.L2:
rjmp .L2
.size main, .-main
.comm v1,8,1
.comm v2,4,1


для -Os -mmcu=attiny2313
Цитата
.file "int64.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
.global __do_copy_data
.global __do_clear_bss
.text
.global main
.type main, @function
main:
push r2
push r3
push r4
push r5
push r6
push r7
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push r16
push r17
/* prologue: function */
/* frame size = 0 */
lds r18,v1
lds r19,v1+1
lds r20,v1+2
lds r21,v1+3
lds r22,v1+4
lds r23,v1+5
lds r24,v1+6
lds r25,v1+7
lds r2,v2
lds r3,(v2)+1
lds r4,(v2)+2
lds r5,(v2)+3
movw r10,r2
movw r12,r4
clr r14
clr r15
ldi r16,lo8(0)
ldi r17,lo8(0)
rcall __udivdi3
movw r24,r18
movw r26,r20
sts v2,r24
sts (v2)+1,r25
sts (v2)+2,r26
sts (v2)+3,r27
ldi r24,lo8(12)
out 50-0x20,r24
.L2:
rjmp .L2
.size main, .-main
.comm v1,8,1
.comm v2,4,1


я не заметил криминала по размеру, на счет правильности нада конечно проверить но.. я изредко интами 64 пользуюсь - вроде работало.

теперь нада лесть в __udivdi3

avr-libc как я понимаю вообще нипричем. операции над стандартными целыми типами - исключительно компиллер в libgcc реализует

тут какято поППа - 3312 инструкций... нада поглядеть исходнички!
посмотрел...

в исходничке libgcc2.c есть реализация на асме операции деления 32/32 , как мне кажется можно по образу и подобию изготовить 64/64

если найдется доброволец взятся за эту учебную задачку высеч сей гранитный монумент я поробую всунуть его под основание фундамента avr GCC, Анатолий Соколов польет это сверху цементом используя комит в транк эсвэна.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 2 2009, 13:42
Сообщение #13


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(klen @ Oct 1 2009, 21:00) *
если найдется доброволец взятся за эту учебную задачку высеч сей гранитный монумент я поробую всунуть его под основание фундамента avr GCC, Анатолий Соколов польет это сверху цементом используя комит в транк эсвэна.
Гляну в выходные, ничего особого в задаче нет.
Можно даже сразу два варианта - глянуть на тему деления без восстановления остатка - немного больше по коду, но быстрее. И подкинуть монетку - что вписывать (на ребро - под условную компиляцию).

Кстати, и это может больше к Анатолию вопрос - если в структуре gcc есть места для делений 64/32, 32/16 и т.п. и их ещё нет, то можно одним махом дописать.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 2 2009, 16:19
Сообщение #14


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(ReAl @ Oct 2 2009, 16:42) *
Можно даже сразу два варианта

Поскольку оно (деление) хавает 24+1 регистров, может еще и в варианте работы с памятью через указатели ? А то ведь столько push/pop' ов некрасиво...
Go to the top of the page
 
+Quote Post
klen
сообщение Oct 2 2009, 18:25
Сообщение #15


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Цитата(_Pasha @ Oct 2 2009, 20:19) *
Поскольку оно (деление) хавает 24+1 регистров, может еще и в варианте работы с памятью через указатели ? А то ведь столько push/pop' ов некрасиво...


интерфейс(способ передачи) входных и выходных переменных определен (компиллером). нада делать с вычислением остатка. иначе компиллер несможет использовать. Вроде предварительно так видется.

К пониманию вопроса.
В GCC как требуют стандарты должны быть реализованы полный минимальный(орнтогональный) набор операций с СТАНДАРТНЫМИ типами языка который он реализует (сложение, вычитание, умножение, деление, сдвиг, ....... ). ВСЕ это реализовано в ВИДЕ КОДА!! То что я описал это "типо ядро". Этот подход гарантирует что компиллер сгенерит код для любой операции с стандартными типами - следовательно гарантировано сможет скомпилять исходник на языке высокого уровня. Далее все интересней. Начинается портирование! нижний слой GCC учитывает то на каком таргете он пасется. Тоесть используется реализация операций с СТАНДАРТНЫМИ типами написанная отделно для этого таргета (обычно это асм). Это позволяет не снижая общности верхненго слоя для любого таргета, учесть ресурсы конкретного процессора. Таким образом например как в нашем случае нет в порте реализации деления 64x64 компиллер берет свою "ппрограмную реализацию" со всеми вытекающими.... зато подход работает всегда!
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 09:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.01518 секунд с 7
ELECTRONIX ©2004-2016