|
|
  |
Несимметрия конечного результата vinavr компилятора |
|
|
|
Nov 17 2012, 17:42
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (=GM= @ Nov 17 2012, 17:28)  могу сделать на асме и сделаю, здесь проблем нет, хотя инлайновый асм в винавре это нечто. Но желание потроллить не дает покоя. То, что в качестве вброса использовался компилятор почти трехлетней давности автора не смущает, а то, что при грамотном использовании инлайн-асм gcc позволяет сделать практичеки чудеса - это для слабых...
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 17 2012, 20:37
|

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

|
А нельзя ли уточнить, какая именно версия avr-gcc/WinAVR сгенерировала код из первого сообщения  ? И с какими ключами  ? А то я вот поднял виртуалку, в которой я виндовые компиляторы на scmRTOS гоняю, у меня там подборка анитквариата есть. Полез вглубь. WinAVR-20100110 (avr-gcc 4.3.3) Код testfn: ldi r30,lo8(ph-4) ldi r31,hi8(ph-4) rjmp .L2 .L3: ld r24,Z com r24 std Z+4,r24 adiw r30,1 .L2: ldi r24,hi8(ph+4) cpi r30,lo8(ph+4) cpc r31,r24 brne .L3 ret WinAVR-20081205 (avr-gcc 4.3.2) Код testfn: ldi r30,lo8(ph-4) ldi r31,hi8(ph-4) rjmp .L2 .L3: ld r24,Z com r24 std Z+4,r24 adiw r30,1 .L2: ldi r24,hi8(ph+4) cpi r30,lo8(ph+4) cpc r31,r24 brne .L3 ret WinAVR-20070525 (avr-gcc 4.1.2) Код testfn: ldi r30,lo8(ph-4) ldi r31,hi8(ph-4) .L2: ld r24,Z com r24 std Z+4,r24 adiw r30,1 ldi r24,hi8(ph+4) cpi r30,lo8(ph+4) cpc r31,r24 brne .L2 ret WinAVR-20060421 (avr-gcc 3.4.6) Код testfn: ldi r30,lo8(ph) ldi r31,hi8(ph) .L4: sbiw r30,4 ld r24,Z adiw r30,4 com r24 st Z+,r24 ldi r24,hi8(ph+8) cpi r30,lo8(ph+8) cpc r31,r24 brne .L4 ret Это все с -Os, для пары версий глянул с -O2 -- то же самое.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Nov 19 2012, 06:52
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Мне вообще представленная ТС строка не нравится Цитата(=GM= @ Nov 17 2012, 01:46)  *(pph++)=~(*(pph-4)); приходится напрягать мозг чтобы понять что произойдёт тут и вспоминать точки следования  ИМХО так значительно прозрачнее Код pph[0] = ~pph[-4]; pph++; ну или даже так Код *pph++ = ~pph[-4] не, так плохо, прогнал, и на компиляции получил предупреждение о возможном неопределённом поведении. {дополнено позже} Цитата(Сергей Борщ @ Nov 17 2012, 21:42)  при грамотном использовании инлайн-асм gcc позволяет сделать практичеки чудеса Это наверно так, но у меня к примеру почему-то простейшая конструкция не выходит (правда я нашёл другой способ решить мою задачу) Код #define makeword16(b0,b1) \ (__extension__({ \ uint8_t __b0 = (uint8_t)(b0); \ uint8_t __b1 = (uint8_t)(b1); \ uint16_t __result; \ __asm__ __volatile__ \ ( \ "\n\t" \ "mov %A0,%A1" "\n\t" \ "mov %B0,%A2" "\n\t" \ : "=r" (__result) /* output operands */ \ : "r" (__b0), /* input operands */ \ "r" (__b1) \ ); \ __result; \ }))
uint8_t b[n]; uint16_t x = makeword16(b[1],b[0]); //read big-endian value ... получаем Код 582: 81 81 ldd r24, Z+1; 0x01 584: 90 81 ld r25, Z 586: 88 2f mov r24, r24 // я плакал:( 588: 99 2f mov r25, r25 // дважды:( Если вы сможете мне помочь буду очень благодарен за развитие кругозора. Спасибо!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Nov 20 2012, 07:40
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Сергей Борщ @ Nov 20 2012, 11:35)  Эта ваша задача решается через union. Будет так же непортируемо, как и с асм-вставкой. Так и сделано (с union наиоптимальнейший результат). Но хотелось бы понять как сие и на асме изобразить. Сейчас не до портируемости, ибо размер сильно важен, а со сдвигами сильно плохо оптимизирует... Код uint16_t x = b0<<8 | b1; никак не меньше 4 инструкций выходит
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Nov 20 2012, 10:25
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (demiurg_spb @ Nov 20 2012, 09:40)  Но хотелось бы понять как сие и на асме изобразить. Знаю, как убрать один из mov: CODE __asm__ __volatile__ \ ( \ "\n\t" \ "mov %B0,%2" "\n\t" \ : "=r" (__result) /* output operands */ \ : "0" (__b0), /* input operands */ \ "r" (__b1) \ ); \ Как объяснить насчет второго - пока не придумал. QUOTE (demiurg_spb @ Nov 20 2012, 09:40)  а со сдвигами сильно плохо оптимизирует... Увы, пока да.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 20 2012, 15:37
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(demiurg_spb @ Nov 19 2012, 06:52)  1) Мне вообще представленная ТС строка не нравится *(pph++)=~(*(pph-4)); приходится напрягать мозг чтобы понять что произойдёт тут и вспоминать точки следования  2) ИМХО так значительно прозрачнее Код pph[0] = ~pph[-4]; pph++; Моя версия компилятора даёт один и тот же ассемблерный код для обоих вариантов 1 и 2. while(pph!=&ph[8]) { *(pph++)=~(*(pph-4)); 98: 80 91 70 00 lds r24, 0x0070 9c: 80 95 com r24 9e: 80 93 74 00 sts 0x0074, r24 a2: 80 91 71 00 lds r24, 0x0071 a6: 80 95 com r24 a8: 80 93 75 00 sts 0x0075, r24 ac: 80 91 72 00 lds r24, 0x0072 b0: 80 95 com r24 b2: 80 93 76 00 sts 0x0076, r24 b6: 80 91 73 00 lds r24, 0x0073 ba: 80 95 com r24 bc: 80 93 77 00 sts 0x0077, r24 И сначала мне больше понравилась ваша версия 2, поскольку никаких предупреждений не было, а в моём варианте было предупреждение: operation on pph may be undefined - операция с pph может быть неопределенной. Но присмотревшись к коду, я понял к чему относится предупреждение. По си коду указатель pph в процессе исполнения кода увеличивается на 4, а в листинге указатель кода никак не участвует, поскольку там цикл развернут и применена прямая адресация! Поэтому компилятор предупреждает, что если вы будете использовать pph дальше, то содержимое указателя может быть отлично от того, на что вы рассчитывали. Я считаю, что лучше пусть будет предупреждение просто как напоминание, что может произойти в дальнейшем. А чудеса с оптимизацией продолжаются. Из такого си кода, больше ничего нет int main(void) //LCD test { unsigned char *pph; unsigned char *pdg; while(1) { pdg=&dig[0]; pph=&ph[4]; while(pph!=&ph[8]) { *(pph++)=~(*(pph-4)); } } } получается такой ассемблерный листинг int main(void) //LCD test { 5e: e4 e7 ldi r30, 0x74 ; 116 60: f0 e0 ldi r31, 0x00 ; 0 pph=&ph[4]; while(pph!=&ph[8]) { *(pph++)=~(*(pph-4)); 62: 34 97 sbiw r30, 0x04 ; 4 64: 80 81 ld r24, Z 66: 34 96 adiw r30, 0x04 ; 4 68: 80 95 com r24 6a: 81 93 st Z+, r24 } while((pdg)!=&dig[4]); pph=&ph[4]; while(pph!=&ph[8]) 6c: 80 e0 ldi r24, 0x00 ; 0 6e: e8 37 cpi r30, 0x78 ; 120 70: f8 07 cpc r31, r24 72: b9 f7 brne .-18 ; 0x62 <main+0x4> 74: 34 97 sbiw r30, 0x04 ; 4 76: f5 cf rjmp .-22 ; 0x62 <main+0x4> Умереть-не встать: теперь компилятор решил не разворачивать цикл while. Не могу понять, по какой причине меняется генерируемый код - по воле левой ноги компилятора или я делаю что-то не так?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Nov 20 2012, 20:51
|

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

|
Цитата(=GM= @ Nov 20 2012, 17:37)  И сначала мне больше понравилась ваша версия 2, поскольку никаких предупреждений не было, а в моём варианте было предупреждение: operation on pph may be undefined - операция с pph может быть неопределенной.
Но присмотревшись к коду, я понял к чему относится предупреждение. По си коду указатель pph в процессе исполнения кода увеличивается на 4, а в листинге указатель кода никак не участвует, поскольку там цикл развернут и применена прямая адресация! Поэтому компилятор предупреждает, что если вы будете использовать pph дальше, то содержимое указателя может быть отлично от того, на что вы рассчитывали. Я считаю, что лучше пусть будет предупреждение просто как напоминание, что может произойти в дальнейшем. Нет, не так. Перепишите цикл следующим образом Код while(pph!=&ph[8]) { *pph=~(*(pph-4)); ++pph; // Ну или pph++ } и убедитесь, что сообщение пропало, хотя указатель так же меняется. Дело тут в том, что эффект от операции pph++ может быть сделан где угодно между уже упомянутыми точками следования. И строка Код { *pph++=~(*(pph-4)); } имеет одинаковое право быть скомпилированной и как вышло, и так: Код { temp_ptr1 = pph pph = pph + 1 <- эта строка имеет право стоять где угодно в пределах от { до; temp_ptr2 = pph - 4 temp_var1 = *temp_ptr2 temp_var1 = ~temp_var1 *temp_ptr1 = temp_var1 ; и на какой-то другой архитектуре это может оказаться выгоднее, например, по скорости исполнения. С-шная строка та же, а результат разный. Стандарт такие места обозначил как undefined behaviour, так как попытка задать что-то жесткое может ухудшить оптимизацию в других местах. Классика.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|