|
Оптимизация кода IAR С++ v5.10 компилятора, весьма странный код... :( |
|
|
|
May 18 2008, 15:47
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Всем привет. Не даёт покоя один момент в коде программы. Вкратце - есть прога на С, которую компилирует IAR C/C++ Compiler for AVR 5.10A/W32 (5.10.1.5). Оптимизация на макс. скорость. Вот фрагмент сгенерированного кода: Код 159 for (a = length; a>0; a--) \ 00000028 2F01 MOV R16, R17 160 { 161 *pBuffer++ = *text++; \ ??usartSendCommand_4: \ 0000002A 01F9 MOVW R31:R30, R19:R18 \ 0000002C 9115 LPM R17, Z+ \ 0000002E 019F MOVW R19:R18, R31:R30 \ 00000030 931D ST X+, R17 162 } \ 00000032 950A DEC R16 \ 00000034 F7D1 BRNE ??usartSendCommand_4 Вот думаю, для чего надо выполнять каждую итерацию цикла команды MOVW? Почему бы не выполнять их один раз перед/после цикла? Не подскажете, уважаемые, каким образом образумить тупонький компилятор? А то запарил он повсюду создавать подобную конструкцию... ЗЫ: вспомнил, что по ИАРу есть отдельная ветка, если нужно, то пусть модераторы перекинут тему туда, извиняюсь...
|
|
|
|
|
 |
Ответов
|
May 19 2008, 16:29
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата Оптимизации, мать их так Ну попробуйте такой вариант - Код #pragma optimize=no_cse __x bool usartSendData(const byte *buffer, byte length) { byte a, len; if (length > sizeof(tx_buffer) || length == 0) { statusTx.length_err = TRUE; return FALSE; } while (statusTx.length); while ((byte)(sizeof(tx_buffer) - (byte)statusTx.queue) < length); len = length; a = sizeof(tx_buffer) - statusTx.pointer; if (length > a) { byte *p=tx_buffer + statusTx.pointer; len -= a; for (;a > 0;a--) *p++ = *buffer++; statusTx.pointer = 0; } statusTx.pointer += len; { byte *p=tx_buffer + statusTx.pointer;; for (;len > 0;len--) *p++ = *buffer++; } statusTx.length = length; UCSR0B |= 1 << UDRIE0; statusTx.length_err = FALSE; return TRUE; }
bool usartSendString(fbyte __flash *pointer) { return usartSendCommand(USART_TEXT, (const void*)pointer, strlen_P(pointer)); }
#pragma optimize=no_cse __z bool usartSendCommand(byte command, const void* pointer, byte length) { byte a; byte *pBuffer;
switch (command) { case USART_TEXT: if (!length || length > USART_MAXDATALENGTH) return FALSE; pBuffer = comm_buffer + USART_PREFFIX; *pBuffer++ = command; *pBuffer++ = length; // copymem_P(pBuffer, (fbyte __flash *)pointer, length); a=length; { byte *p=pBuffer; fbyte __flash* text; text = (fbyte __flash*)pointer; do { *p++ = *text++; } while(--a); *p=CalculateCRC(pBuffer, length); } break; default: return FALSE; } pBuffer = comm_buffer; *pBuffer++ = 'S'; *pBuffer = 'N'; return usartSendData(comm_buffer, length + USART_FRONTEND); } Тут много магии - отдельные указатели (почему-то иногда очень плохо у IAR'а по ходу выполнения функции переменные перемещаются по регистрам), no_cse... А в общем итоге видимо проблема заключается в том, что использование структур и двух указателей сразу приводит к нехватке регистровых пар. Видимо, тут GCC был бы на высоте. Цитата Обработчики прерываний (в виде единой функции!) с длиннющим сохранением регистров на стёк, когда на асме обошёлся бы парой-тройкой... Если какие-то функции другие вызываются - будет сохранение всех scratch-регистров, если нет - все будет хорошо. Цитата Вот зачем надо было вводить второй стёк для данных? Вот GCC не делает второй стек для данных. Все хорошо, пока переменные одной функции помещаются в регистрах. Как только надо исполнить стековую переменную - начинается мрак, там такой код для пролога/эпилога, что с непривычки за голову хватаешься... Тут конечно, надо бы было сделать 2 комманды при разработке ядра, LDD r,SP+disp и STD SP+disp,r и пару комманд увеличения/уменьшения указателя стека - и тогда бы здорово помогло... Но поезд ушел 10 лет назад
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
May 19 2008, 16:52
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(Rst7 @ May 19 2008, 21:29)  Ну попробуйте такой вариант ... Если какие-то функции другие вызываются - будет сохранение всех scratch-регистров, если нет - все будет хорошо. ... Вот GCC не делает второй стек для данных. Все хорошо, пока переменные одной функции помещаются в регистрах. Как только надо исполнить стековую переменную - начинается мрак, там такой код для пролога/эпилога, что с непривычки за голову хватаешься... Тут конечно, надо бы было сделать 2 комманды при разработке ядра, LDD r,SP+disp и STD SP+disp,r и пару комманд увеличения/уменьшения указателя стека - и тогда бы здорово помогло... Но поезд ушел 10 лет назад  Спасибо Дмитрий, попробую  Насчёт прерываний - в том то и дело, что каких-либо вызовов функций нет, а сохраняется по 7-9 регистров на CSTACK. Возможно, слишком громоздкий код получается, конечно. По стеку понятно, для большого кол-ва переменных это будет выгодно, наверное, хотя у себя я пока не наблюдал подгрузку данных с регистра Y... ЗЫ: Хочу передать Вам большой респект, как кодеру известной в своё время команды Codebusters До сих пор помню Satisfaction megademo, сколько раз тогда запускал её и любовался эффектами и музыкой... Приятно, что этот форум посещают подобные вам люди
|
|
|
|
|
May 19 2008, 18:05
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Да, чудесным образом лишние инструкции исчезли! Как я понял, всё это путём небольшого изменения порядка следования команд, введения дополнительных указателей/или переменных для исключения лишних вычислений и парочкой прагм... Да-а, башку можно сломать от такого напряга В общем вот что получилось в итоге: Код bool usartSendData(const byte *buffer, byte length) { byte a, len; if (length > sizeof(tx_buffer) || length == 0) { statusTx.length_err = TRUE; return FALSE; } while (statusTx.length); while ((byte)(sizeof(tx_buffer) - (byte)statusTx.queue) < length); len = length; a = sizeof(tx_buffer) - statusTx.pointer; if (length > a) { byte *p=tx_buffer + statusTx.pointer; len -= a; for (;a > 0;a--) *p++ = *buffer++; statusTx.pointer = 0; } a = len; byte *p=tx_buffer + statusTx.pointer; for (;a > 0;a--) *p++ = *buffer++; statusTx.pointer += len; statusTx.length = length; UCSR0B |= 1 << UDRIE0; statusTx.length_err = FALSE; return TRUE; }
#pragma optimize=no_cse __z bool usartSendCommand(byte command, const void* pointer, byte length) { byte a; byte *pBuffer; switch (command) { case USART_TEXT: if (!length || length > USART_MAXDATALENGTH) return FALSE; pBuffer = comm_buffer + USART_PREFFIX; *pBuffer++ = command; *pBuffer++ = length; a=length; byte *p; p = pBuffer; fbyte __flash* text; text = (fbyte __flash*)pointer; while(a--) *p++ = *text++; *p = CalculateCRC(pBuffer, length); break; default: return FALSE; } pBuffer = comm_buffer; *pBuffer++ = 'S'; *pBuffer = 'N'; return usartSendData(comm_buffer, length + USART_FRONTEND); } Все три цикла копирования стали просто идеальными! Причём первая функция сохраняет "стройность" и без "прагмы" и "__x". Магия?
|
|
|
|
Сообщений в этой теме
sonycman Оптимизация кода IAR С++ v5.10 компилятора May 18 2008, 15:47 Diz Может, попробовать через стандартную memcpy ? May 18 2008, 15:58 sonycman Цитата(Diz @ May 18 2008, 20:58) Может, п... May 18 2008, 16:06 SasaVitebsk Похоже указатель *text объявлен как volatile.
Попр... May 18 2008, 16:42 sonycman Цитата(SasaVitebsk @ May 18 2008, 21:42) ... May 18 2008, 17:33 Diz Если не ошибаюсь, в IAR для флеша есть memcpy_P. May 18 2008, 17:47 vet с флэш работает memcpy_P().
её объявление содержит... May 18 2008, 17:47 sonycman Цитата(Diz @ May 18 2008, 22:47) Если не ... May 18 2008, 17:51  zltigo Цитата(sonycman @ May 18 2008, 19:51) ...... May 18 2008, 21:04 IgorKossak Если речь идёт конкретно об IAR и функция не может... May 19 2008, 05:44 sonycman Цитата(zltigo @ May 19 2008, 02:04) Не ог... May 19 2008, 13:40  KRS Цитата(sonycman @ May 19 2008, 17:40) ...... May 19 2008, 15:03   sonycman Цитата(KRS @ May 19 2008, 20:03) так в да... May 19 2008, 15:10    zltigo Цитата(sonycman @ May 19 2008, 17:10) Опт... May 19 2008, 15:31     sonycman Цитата(zltigo @ May 19 2008, 20:31) Ну ещ... May 19 2008, 15:55 Rst7 Цитата...попробовал вот так:
из этого никак не мог... May 19 2008, 14:04 sonycman Цитата(Rst7 @ May 19 2008, 19:04) из этог... May 19 2008, 14:11   zltigo Цитата(sonycman @ May 19 2008, 20:05) Да-... May 19 2008, 18:09 singlskv Цитата(Rst7 @ May 19 2008, 20:29) Тут мно... May 19 2008, 18:36 Rst7 ЦитатаПроблемы только с переносимостью между компи... May 20 2008, 07:01 singlskv Цитата(Rst7 @ May 20 2008, 11:01) Это пок... May 20 2008, 07:31 sonycman Цитата(Rst7 @ May 20 2008, 11:01) делаем ... May 20 2008, 11:58  singlskv Цитата(sonycman @ May 20 2008, 15:58) Хм,... May 20 2008, 12:09   sonycman Цитата(singlskv @ May 20 2008, 16:09) Там... May 20 2008, 12:18 Andreas1 Еще непонятки с оптимизацией, правда в IAR AVR 4.3... May 21 2008, 12:54 Сергей Борщ Цитата(Andreas1 @ May 21 2008, 15:54) P.S... May 21 2008, 14:32  sonycman Цитата(Сергей Борщ @ May 21 2008, 19:32) ... May 26 2008, 17:12 Rst7 Цитата3 варианта одного и того-же
Местные телепат... May 21 2008, 13:06 Waso Немного не в тему, потому как речь о версии ИАР 4.... Nov 26 2010, 18:30 demiurg_spb А если так:
Кодunion { // для доступа к одной я... Nov 27 2010, 18:25 Dog Pawlowa Цитата(Waso @ Nov 26 2010, 21:30) Немного... Nov 28 2010, 06:37 Xenia Вот так напишите и будет вам щастье:
Кодvoid ma... Nov 28 2010, 07:37 Waso demiurg_spb, неа, не канает.
Xenia, Dog Pawlowa, ... Nov 28 2010, 19:33 rezident Цитата(Waso @ Nov 29 2010, 00:33) Где про... Nov 28 2010, 20:43  Сергей Борщ QUOTE (rezident @ Nov 28 2010, 22:43) В с... Nov 28 2010, 22:18 Waso Спасибо. Каюсь. Грешен. Ненавижу читать стандарты... Nov 29 2010, 08:17
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|