Bitove polia a optimalizacia kody Was: STM32F051K6U7 ma USART2 ?

Miroslav Mraz mraz na seznam.cz
Neděle Březen 15 23:13:02 CET 2015


Lze to optimalizovat ručně:

typedef unsigned short bit_type;

union xbu {
   struct {
     bit_type b1:1;
     bit_type b2:6;
     bit_type b3:1;
     bit_type b4:1;
     bit_type b5:6;
     bit_type b6:1;
   } b;
   bit_type w;
};
static xbu b;

void test (void) {
   register xbu t;
   t.w = b.w;
   t.b.b1=1;
   t.b.b5=1;
   b.w = t.w;
}

Blbý co ? Ale ten gcc se fakt chová divně - tedy ten přístup po bytech 
bych nečekal. Když jsem to kdysi přepisoval, tak jsem to zkoumal dost 
podrobně (CM0) a chovalo se to celkem mravně. Tedy nastavení / nulování 
jednoho bitu v registru bylo úplně stejné jako použití |= příp. &= na 
celý uint32. Možná že překlad pro CM0 se chová jinak než CM3. Je pozdě, 
končím.

Mrazík

Dne 15.3.2015 v 21:58 Milan B. napsal(a):
> On 15. 3. 2015 18:18, Miroslav Mraz wrote:
>> Dovolím si k tomu ještě jednu drzou poznámku. Přesně toto je důvod,
>> proč přepsat definice registrů do bitových polí.
>
> Ked uz sa tu odporucaju bitove polia, tak ma napadlo overit, ako ich
> kompilator dokaze optimalizovat.
>
> Skusal som GCC  4.9.3 20141119 (ARM Embedded). Vysledok bol zaujimavy,
> tak som si ho overil na dalsich dvoch portoch - MSP430 (4.9.1) a x86
> (4.8.2) - s rovnakym vysledkom, takze je to vlastnost GCC ako takeho:
>
> GCC dokaze spojit do jednej operacie nastavovanie jednobitovych poloziek
> v ramci jednoho byte. Akonahle sa nastavuju polozky patriace do roznych
> byte, robi to na viackrat.
> Viacbitove polozky sa vzdy riesia samostatne.
>
> Priklad:
> Majme 16-bitove pole:
> struct {
>   unsigned int b1:1;
>   unsigned int b2:6;
>   unsigned int b3:1;
>   unsigned int b4:1;
>   unsigned int b5:6;
>   unsigned int b6:1;
> } b;
>
> Velkost jednoduchej funkcie nastavujucej dve jednobitove polozky (aj s
> prologom a epilogom, nechcelo sa mi ich odpocitavat):
> void test()
> {
>    b.b1=1;
>    b.b3=1;
> }
>
> je u ARM (kompilovane s -march=armv7e-m -mthumb a optimalizaciami -O2 aj
> -Os) 16 byte. Oba bity su v ramci jednoho byte.
>
> Ak su jednobitove polozky v dvoch roznych byte:
>    b.b1=1;
>    b.b4=1;
> Tak je velkost kodu 24 byte.
>
> Ak su polozky v jednom byte, ale jedno je viacbitove:
>   b.b1=1;
>   b.b2=1;
> Tak je velkost 20 byte (-O2) alebo 24 byte (-Os).
>
> A nakoniec to iste, ale viacbitova polozka je v druhom byte:
>   b.b1=1;
>   b.b5=1;
> Tu je velkost kodu 24 byte (-O2) alebo 28 byte (-Os).
>
> Najvacsie prekvapenie nastalo, ked som to porovnal s "klasickym"
> nastavovanim bitov cez bitovy OR:
>   a|=0x1001u;
> Velkost kodu bola 20 byte - trochu viac, ako som ocakaval.
>
> Pohlad do vygenerovaneho kodu priniesol prekvapenie:
>   orr     r3, r3, #4096
>   orr     r3, r3, #1
>
> Na tuto - trufam si povedat sprostost - nemam vysvetlenie. Toto je ale
> ciste problem portu GCC pre ARM, ostatne komilatory nemali s konstantou
> problem:
> MSP430: BIS.W   #4097, &a
> x86:    orw     $4097, a(%rip)
>
> Takze optimalizacia prace s bitovymi polami nie je nic moc, a kvalita
> ARM portu GCC tiez zrejme nestoji za vela.
>
> -m-
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>


Další informace o konferenci Hw-list