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