Automaticke pretypovani u AVR-GCC
Milan B.
milan@bastl.sk
Středa Červenec 22 19:24:13 CEST 2009
Obavam sa, ze to riesenie nie je.
Najprv trochu vyskumu:
Vezmime si tri pripady:
A. if ( 3 & Status) ...
B. if ( 3==(3 & Status) ...
C. if ( ss = (3 & Status ) ... // ss je tiez unsigned char
Pri skompilovani avr-gcc (verzia 4.3.2) *bez optimalizacie* pripady A aj
B su skompilovane ako 16-bitove, pripad C je skompilovany ako 8-bitovy.
Pokial zapneme optimalizaciu, tak aj pripad B sa zmeni na 8-bitovy
(napriek tomu, ze je tam to cislo 3)
Avsak ci uz je optimalizacia zapnuta alebo nie, vyrazy v pripadoch A a B
su vyhodnocovane ako 16-bitove. Pripad B je upraveny az pri neskorsej
optimalizacii - prezretim dump suborov (avr-gcc -fdump-rtl-all) sa da
presne zistit, kedy sa to stalo (and:HI (half-integer )sa zmeni na
and:QI (quarter-integer)). Z tychto dumpov je tiez viditelne, ze oba
pripady A a B boli povodne vyhodnotene ako 16-bitove a C ako 8-bitovy
Takze tu vznika domnienka: GCC sa snazi co najviac pracovat s operandmi
v nativnej sirke slova, predpokladajuc ze CPU s takymito operandmi vie
pracovat najefektivnejsie. Ak ma k tomu nejaky dovod (napr. vysledok sa
uklada do premennej konkretneho typu), tak svoje chovanie moze zmenit -
to je pripad C. Kedze avr-gcc ma definovanu nativnu sirku slova 16 bit
tak pripady A a B su spracovane ako 16-bitove (pretoze vysledok sa len
pouzije pri porovnani, nikde sa neuklada). Ak si ten isty priklad
vyskusame s x86 gcc, dostaneme sa k 32-bitovym operaciam - co len
potvrdzuje tuto domnienku
(Len na okraj: ak v pripade C je premenna ss 32-bitova, cela transakcia
sa udeje v 32 bitoch aj na AVR... )
Takze skutocnost, ze pripad B bol; prelozeny ako 8-bitovy nema vela
spolocne s tym, ako vyzera zdrojovy kod, ale co s nim urobili zaverercne
optimalizacie.
Samozrejme ostava otazka, preco kompilator nezoptimalizoval pripad A.
Pravdepodobne na zaklade popisu architektury (machine description),
ktoru dodali autori portu, kompilator nenasiel vhodnu redukciu ... ( v
pripade A kompilator generuje pseudoinstrukciu tsthi a v pripade B cmphi
- pre cmphi je zda sa moznost substitucie na bytove operacie, zatial co
pre tsthi sa jednoducho generuje kod - ale hlbsie skumat sa mi to
nechce, to som len letmo nahliadol do machine description)
Takze da sa povedat, ze GCC pracuje perfektne a generuje optimalny kod -
pre take AVR, ake mu zadefinovali autori portu avr-gcc, tj. AVR s
nativnou sirkou slova 16bit a s takym machine description, ake je. Chova
sa podla popisu architektury, nie podla nalady. A asi tazko s tym nieco
urobite - jedine ze by ste vylepsili popis architektury (najdete ho v
zdrojakoch gcc v adresari gcc/config/avr/avr.md)
Len poznamka na zaver:
Uvedomte si, ze pri vyssich jazykoch je dolezite, ci dostanete vysledok
podla specifikacie. Vo vasom pripade, ci podmienka funguje tak ako ma.
To, ako to kompilator prelozi, je jeho vec a - s prepacenim - nic vas do
toho nie je :). To je proste princip vyssich jazykov. Ak chcete pocitat
takty a instrukcie - mate assembler. Ono ked vytunite program v C pre
nejaky kompilator, s novou verziou alebu znackou kompilatora ste zasa na
zaciatku a o prenositelnosti sa neda hovorit - ale mam dojem, ze to vam
tu uz niekto povedal.
-m-
Tomáš Halabala wrote:
> Děkuji, jo toto je řešení, ale co mě na tom nejvíce zaráží je, jak jsem
> psal, že v jednom případě překladač tu trojku nerozšířil a v jiném místě
> programu s úplně stejným zápisem pouze s jinými názvy proměnných tu
> trojku převedl na int, což jak píšete odpovídá ANSI C. Ale proč to tedy
> dodržuje překladač podle nálady? To už asi zůstane nezodpovězeno.
> Odpovědí je zřejmě asi IAR.
>
> Použil jsem C, protože se jedná o velmi rozsáhlý program a samozřejmě ty
> nejkritičtější části jsou psané v assembleru. Administrativní část je v
> C s tím, že neustále kontroluji efektivnost překladu. Slibuji si od toho
> přece jen snadnější přenositelnost na jiné MCU a CPU, což je také
> směrodatné.
>
> Tomáš
>
> Miroslav Šinko napsal(a):
>
>> Myslim, ze problem je v konverziach na int podla ANSI C, kde cislo 3
>> je implicitne 16-bit. Kedysi sa to tu preberalo.
>>
>> Pohral som sa s AVR-GCC. Riesenim je takyto zapis:
>>
>> void fce(void)
>> {
>> U8 val=3;
>> if (val & Status) { ...
>> ..
>> }
>>
>> pre druhy priklad:
>> void fce(void)
>> {
>> U8 val1=3, val2=3;
>> if ((val1 & Status) == val2) { ...
>> ..
>> }
>>
>> Pri optimalizacii O1 nevytvara na zasobniku priestor pre val (val1,2)
>> a kod je taky, ako si predstavujete :-)
>>
>> if(val & status)
>> 136: 80 91 63 00 lds r24, 0x0063
>> 13a: 83 70 andi r24, 0x03 ; 3
>> 13c: 11 f0 breq .+4 ; 0x142 <fce+0xc>
>>
>>
>> if((val1 & status) == val2)
>> 136: 80 91 63 00 lds r24, 0x0063
>> 13a: 83 70 andi r24, 0x03 ; 3
>> 13c: 83 30 cpi r24, 0x03 ; 3
>> 13e: 11 f4 brne .+4 ; 0x144 <fce+0xe>
>>
>> miro
>>
>> PS: wek by Vam este napisal nieco o vhodnosti C na casovo kriticke aplikacie :-)
>>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list@list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>
Další informace o konferenci Hw-list