FAQ | Points | Add... | Recent posts | Search | Register | Log in


call-clobbered register, opce optymalizacji gcc.


Post new topic  Reply to topic      Main Page -> Forum Index -> Programming Generally -> call-clobbered register, opce optymalizacji gcc.
Author
Message
trol.six
Poziom 20
Poziom 20


Joined: 29 Oct 2005
Posts: 1086
Location: Krakow

Post#1 Post from the author of the topic 06 Apr 2007 19:56   

call-clobbered register


mam pytanie, moze ktos mi rozjaśni w głowie, bo co nie co sie znam, ale skąd moze brac sie taki niuans:
deklaracja zmiennej z przypisaniem do rejestru w avr:
Code:
register unsigned char data asm("r3");


niektóre funkcje są OK np:
Code:
data |= 0x02;
 140:   22 60          ori   r3, 0x02   ; 2

a w innej funkcji do niczego i używa r18:
Code:
 4e8:   41 fd          sbrc   r18, 1
 4ea:   17 c0          rjmp   .+46        ; 0x51a <__stack+0xbb>


Oczywiście kompilator uprzedza:
Quote:
warning: call-clobbered register used for global register variable

Przy optymalizacji -Os kod jest generowany poprawnie przy -O2 jest jak powyżej. Czytam o opcjach optymalizcyjnych gcc. Domyslam sie że jakas optymalizacja tutaj ma coś do powiedzenia, ktoś wie która? I czemu to tak.
Back to top
   
eP
Poziom 19
Poziom 19


Joined: 02 Oct 2006
Posts: 798
Location: Tak

Post#2 11 Apr 2007 09:45   

Re: call-clobbered register


trol.six wrote:
Przy optymalizacji -Os kod jest generowany poprawnie przy -O2 jest jak powyżej. Czytam o opcjach optymalizcyjnych gcc. Domyslam sie że jakas optymalizacja tutaj ma coś do powiedzenia, ktoś wie która? I czemu to tak.


Jezeli rejestr przechowuje zmienna globalna to kompilator stara sie zamiast tegoz rejestru uzyc chwilowo innego bedacego do dyspozycji - wolnego.
Oczywiscie jezeli zazadasz od kompilatora przy pomocy wyboru odpowiednich opcji do kompilacji aby stosowal sie scisle do Twoich zyczen to on sie zastosuje tyle ze kod programu moze sie przez to wydluzyc i stac sie mniej efektywnym, bo w danej chwili trzeba bedzie dolozyc instrukcje zwolnienia zajetego rejestru by moc go uzywac w innym celu, a na koniec instrukcje przywrocenia mu wartosci poczatkowej.

Pozdrawiam
Back to top
   
Google

Google Adsense


Post# 11 Apr 2007 09:45   





Back to top
   
trol.six
Poziom 20
Poziom 20


Joined: 29 Oct 2005
Posts: 1086
Location: Krakow

Post#3 Post from the author of the topic 11 Apr 2007 12:19   

Re: call-clobbered register


Oki, tyle ze to troche bez sensu, po co uzywa r18 jak ma używać r2. Wtedy zamist jednego zadeklarowanego r2, używa dwóch r2 i r18 w zależnosci od miejsca w programie. Co skutkuje niewłaściwym działeniem programu. I koniecznoscią pisania w inny sposób.

Ja sie domyślam że w jakis przypadkach może to przynieść korzyść, tylko wydaje mi sie to dość drastyczne.

W zasadzie to przy bardzo dużym programie, gdzie duża ilosć danych przewala sie przez przerwania (bo to one są tutaj głownym czynnikiem sprawczym), to musiałbym chyba wszystkie dane zapisać jako volatile, to raz, co i tak pogarsza kod w relacji do -Os,

Po to sobie stosuje zmienna globalną na stałe przypisaną do rejestru r2, żeby mieć do niej dostęp z każdego punktu programu, i to bardzo szybko.

Bo deklaracja zmiennej np:
Code:
volatile unsigned char data

skutkuje dośc rozdmuchanym kodem, gdyż za każdym razem procesor pobiera zmienna z pamieci do rejestru, a tak mam ją w r2, dzieki czemu szybkość kodu jest znacznie wyższa.

To i tak nie jest to co w asemblerze, ale przy opcjach gdzie zależy nam na czasie poprawia troche całość. A wydawało mi sie że deklaracja na stałe przypisania danej do rejestru jest stała, ale widze ze jednak czasem kompilator ma humor i olewa to przypisanie.

To po kiego grzyba ja to przypisanie na stałe zmiennej do rejestru robie, skoro kompilator ma to gdzieś?

Nie doszukałem sie która opcja gcc powoduje taką optymalizacje, bo moze by mnie troche bardziej oświeciło
Back to top
   
eP
Poziom 19
Poziom 19


Joined: 02 Oct 2006
Posts: 798
Location: Tak

Post#4 11 Apr 2007 16:02   

Re: call-clobbered register


trol.six wrote:
Oki, tyle ze to troche bez sensu, po co uzywa r18 jak ma używać r2. Wtedy zamist jednego zadeklarowanego r2, używa dwóch r2 i r18 w zależnosci od miejsca w programie. Co skutkuje niewłaściwym działeniem programu. I koniecznoscią pisania w inny sposób.

Sorry Kolego ale za sens to odpowiadasz Ty a nie kompilator - po to masz wlasnie miedzy innymi opcje kompilacji.
Zakladam ze rozrozniasz przypadki przekazywania argumentow do funkcji przez wartosc i przez referencje.
Oraz nie sa Ci obce zakresy waznosci zmiennych w programie.

trol.six wrote:

Ja sie domyślam że w jakis przypadkach może to przynieść korzyść, tylko wydaje mi sie to dość drastyczne.

W zasadzie to przy bardzo dużym programie, gdzie duża ilosć danych przewala sie przez przerwania (bo to one są tutaj głownym czynnikiem sprawczym), to musiałbym chyba wszystkie dane zapisać jako volatile, to raz, co i tak pogarsza kod w relacji do -Os,

Po to sobie stosuje zmienna globalną na stałe przypisaną do rejestru r2, żeby mieć do niej dostęp z każdego punktu programu, i to bardzo szybko.

Bo deklaracja zmiennej np:
Code:
volatile unsigned char data

skutkuje dośc rozdmuchanym kodem, gdyż za każdym razem procesor pobiera zmienna z pamieci do rejestru, a tak mam ją w r2, dzieki czemu szybkość kodu jest znacznie wyższa.

To i tak nie jest to co w asemblerze, ale przy opcjach gdzie zależy nam na czasie poprawia troche całość. A wydawało mi sie że deklaracja na stałe przypisania danej do rejestru jest stała, ale widze ze jednak czasem kompilator ma humor i olewa to przypisanie.

Nie, kompilator niczego nie olewa tylko kompiluje kod wedle Twoich osobistych zyczen i zazalen ktore mu zglaszasz ustawiajac lub nie odpowiednie opcje kompilacji.

trol.six wrote:

To po kiego grzyba ja to przypisanie na stałe zmiennej do rejestru robie, skoro kompilator ma to gdzieś?

A to po kiego grzyba uruchamiasz go z takim a nie innym zestawem opcji ? :D

trol.six wrote:

Nie doszukałem sie która opcja gcc powoduje taką optymalizacje, bo moze by mnie troche bardziej oświeciło


Ja tez sie nie doszukalem, ale najwyrazniej widac ze kompilator stara sie myslec za Ciebie i wysyla ci odpowiednie Warningi aby cie zmotywowac do dokladniejszego przestudiowania sensu opcji z ktorymi go uruchamiasz.

Przypuszczam ze bylbys duzo bardziej zaskoczony gdyby sie okazalo ze jakas funkcja zmienia sobie wartosc Twojej zmiennej globalnej tylko dlatego ze ma zdefiniowane w swoim ciele by korzystac z tego samego rejestru do jakichs swoich celow, ktory sluzy do przechowywania Twojej zmiennej globalnej.
Back to top
   
trol.six
Poziom 20
Poziom 20


Joined: 29 Oct 2005
Posts: 1086
Location: Krakow

Post#5 Post from the author of the topic 11 Apr 2007 17:50   

Re: call-clobbered register


OKi, ja to wiem wszystko co napisałeś, przeciez napisałem że opcja -Os generuje poprawny kod, i napisałem że działa tutaj jakaś opcja optymalizacyjna.

Dlatego interesuje mnie co takiego kryje sie za ruszaniem moich zmiennych przypisanych do rejestrów, przez kompilator, bo moim zdaniem deklaracje takich zmiennych są dość poważne. Widać nie na tyle poważne.

opcja -O2 jest opcja dość standartowa, i moim zdaniem nie powinna aż tak bardzo ingerować w kod.

Dlatego zadałem pytanie na forum, bo moze ktoś wie albo naprowadzi mnie skąd sie to bierze. Bo jak to działa w praktyce to ja wiem, bo mam przed oczyma w postaci kodu wynikowego a wyniki umieszczone tutaj.

No chyba że zakres zmiennej globalnej przypisanej do r2, nie obejmuje funkcji main. No to faktycznie mam braki.
Back to top
   
Google

Google Adsense


Post# Post from the author of the topic 11 Apr 2007 17:50   





Back to top
   
szelus
Poziom 20
Poziom 20


Joined: 12 Jul 2004
Posts: 1016

Post#6 11 Apr 2007 19:25   

Re: call-clobbered register


Ten warning wydaje sie sugerować, że użyty rejestr (r3) nie jest przechowywany przez wywoływane funkcje (tzn. że nie jest to "dobry" rejestr na zmienną globalną, bo funkcje biblioteczne mogą go niszczyć). Czy ten warning pojawia sie niezależnie od poziomu optymalizacji, czy tylko przy -O2?
Co do ignorowania Twojej deklaracji, to trochę mało tu danych. Wybrałeś fragmenty, że tak powiem, tendencyjnie. :wink: Bez obejrzenia większych kawałków programu trudno dywagować.
Masz więcej, niż jeden plik źródłowy?
Jaka wersja gcc?
Back to top
   
trol.six
Poziom 20
Poziom 20


Joined: 29 Oct 2005
Posts: 1086
Location: Krakow

Post#7 Post from the author of the topic 11 Apr 2007 22:06   

Re: call-clobbered register


wersja gcc avr-3.4.4

warning pojawia sie tylko wtedy kiedy źle jest generowny kod, czyli przy optymalizacji -O2, choć teraz po uproszczeniu nawet sie nie pojawia.

Zdarzyłomi sie że taka zmienna przypisana do rejestru była w innym rejestrze, albo w ogóle w pamieci, tak jak sugerujesz ze jakaś funkcja bibioteczna byłaby używana, to kompilator przesówał ją do innego rejestru.
Natomiast nigdy nie mailem takiego problemu że dwie funkcje korzystają z dwu róznych rejestrów.

Sprawa wygląda tak, że jak uproszcze program to jest OKi, a jak dam troche wiecej linijek to bluzga. Ja wiem dlaczego sie bluzga, i zaraz to wam pokaże:

Code:

register unsigned char cz_set asm("r2");
register unsigned char co_st asm("r4");

int main ( void )
{
cz_set = 0;
co_st = 0;

sei();

// --- ja wiem brzydka petla ale while(1){} dziąła tak samo
BIBI:

if ( co_st & 0x02 )
{
co_st &= ~( 0x02 );

liczba_cyfra ( cz_sek/10, 2 );
}


if ( co_st & 0x01 ) {

if ( cz_set == 120 ){

liczba_cyfra ( ' ', 0 );

}
}

sei();

goto BIBI;

return (0);
}


Code:
00000256 <main>:
 256:   cf e5          ldi   r28, 0x5F   ; 95
 258:   d4 e0          ldi   r29, 0x04   ; 4
 25a:   de bf          out   0x3e, r29   ; 62
 25c:   cd bf          out   0x3d, r28   ; 61

 25e:   22 24          eor   r2, r2  // ---- nasze rejestry

 260:   42 2c          mov   r4, r2
 262:   78 94          sei

 264:   82 2d          mov   r24, r2  // ---- kompilator przepisuje do r24 ale o co?

 266:   99 27          eor   r25, r25
 268:   81 fd          sbrc   r24, 1
 26a:   08 c0          rjmp   .+16        ; 0x27c <main+0x26>
 26c:   80 ff          sbrs   r24, 0
 26e:   03 c0          rjmp   .+6         ; 0x276 <main+0x20>
 270:   28 e7          ldi   r18, 0x78   ; 120
 272:   22 16          cp   r2, r18
 274:   71 f0          breq   .+28        ; 0x292 <main+0x3c>
 276:   78 94          sei

 278:   81 ff          sbrs   r24, 1  // ---- tutaj mamy skok petli i brak odswieaznia r24 wqartoscia r2

 27a:   f8 cf          rjmp   .-16        ; 0x26c <main+0x16>
 27c:   2d ef          ldi   r18, 0xFD   ; 253
 27e:   42 22          and   r4, r18
 280:   80 91 72 00    lds   r24, 0x0072
 284:   6a e0          ldi   r22, 0x0A   ; 10
 286:   9e d2          rcall   .+1340      ; 0x7c4 <__udivmodqi4>
 288:   62 e0          ldi   r22, 0x02   ; 2
 28a:   41 df          rcall   .-382       ; 0x10e <liczba_cyfra>
 28c:   84 2d          mov   r24, r4
 28e:   99 27          eor   r25, r25
 290:   ed cf          rjmp   .-38        ; 0x26c <main+0x16>
 292:   60 e0          ldi   r22, 0x00   ; 0
 294:   80 e2          ldi   r24, 0x20   ; 32
 296:   3b df          rcall   .-394       ; 0x10e <liczba_cyfra>
 298:   84 2d          mov   r24, r4
 29a:   99 27          eor   r25, r25
 29c:   78 94          sei
 29e:   ec cf          rjmp   .-40        ; 0x278 <main+0x22>


a jak wyglada skompilowany z opcją -Os

Code:
00000212 <main>:
 212:   cf e5          ldi   r28, 0x5F   ; 95
 214:   d4 e0          ldi   r29, 0x04   ; 4
 216:   de bf          out   0x3e, r29   ; 62
 218:   cd bf          out   0x3d, r28   ; 61
 21a:   22 24          eor   r2, r2
 21c:   42 2c          mov   r4, r2
 21e:   78 94          sei

 220:   41 fe          sbrs   r4, 1 // ----- poprawne porównanie

 222:   08 c0          rjmp   .+16        ; 0x234 <main+0x22>
 224:   8d ef          ldi   r24, 0xFD   ; 253
 226:   48 22          and   r4, r24
 228:   80 91 72 00    lds   r24, 0x0072
 22c:   6a e0          ldi   r22, 0x0A   ; 10
 22e:   75 d2          rcall   .+1258      ; 0x71a <__udivmodqi4>
 230:   62 e0          ldi   r22, 0x02   ; 2
 232:   20 df          rcall   .-448       ; 0x74 <liczba_cyfra>
 234:   40 fe          sbrs   r4, 0
 236:   06 c0          rjmp   .+12        ; 0x244 <main+0x32>
 238:   88 e7          ldi   r24, 0x78   ; 120
 23a:   28 16          cp   r2, r24
 23c:   19 f4          brne   .+6         ; 0x244 <main+0x32>
 23e:   60 e0          ldi   r22, 0x00   ; 0
 240:   80 e2          ldi   r24, 0x20   ; 32
 242:   18 df          rcall   .-464       ; 0x74 <liczba_cyfra>
 244:   78 94          sei
 246:   ec cf          rjmp   .-40        ; 0x220 <main+0xe>


W zasadzie jak troche zmienie kod to zawsze cos tam przy -O2 namiesza, tu jest taki przykład.

Wiec sprawa mi sie tak ze sobie chłopina przapisuje do innych rejestrów i z tamtych nie korzysta. Tylko w jakim celu?

Albo liczy adres skoku w petli pomijając przepisanie zmiennych, co czasem może być optymalizacją, ale tutaj wyraźnie ma przypisanie rejetrów do zmiennych i nie podoba mi sie ze se przepisuje do innych.

Poniewaz ja już dosyć mocno namieszałem, możę to nie być to co na początku, ale mniej wiecej coś w tym stylu.
Back to top
   
szelus
Poziom 20
Poziom 20


Joined: 12 Jul 2004
Posts: 1016

Post#8 12 Apr 2007 10:53helpful post - solution   

Re: call-clobbered register


Wersja 3.4.4 nie jest najświeższa (chociaż ja tez korzystam z 3.4.3). Z tego co pamiętam, były zastrzeżenia co do optymalności generowanego kodu.

Co do samego kodu, to błędu nie widzę. Tzn. przy -O2 kod nie jest może najoptymalniejszy (zawsze możesz jeszcze sprawdzić -O3), ale generalnie poprawny.

Jeżeli chodzi o brak odświeżania r24 z r2 to jest to OK. W instrukcji gcc jest wyraźnie napisane, że nie wolno używać zmiennych przypisanych na stałe do rejestrów w przerwaniach. Zresztą, brak tu volatile. Zatem kompilator całkiem poprawnie zakłada, że w tym miejscu wartość r2 nie mogła ulec zmianie.

Nawiasem mówiąc, kod, który pokazałeś nie jest z tej wersji źródeł. W obu wersjach brak w kodzie wynikowym czegoś, co odpowiadałoby "if ( co_st & 0x02 )" w kodzie źródłowym. Z kolei w kodzie źródłowym brak instrukcji out, które są w kodzie wynikowym.
Back to top
   
trol.six
Poziom 20
Poziom 20


Joined: 29 Oct 2005
Posts: 1086
Location: Krakow

Post#9 Post from the author of the topic 12 Apr 2007 11:57   

Re: call-clobbered register


Niestety musze cie zmartwić , ale jest to kod bezpośrednio przekopiowany z kompilacji. Kod if jest tutaj 268: 81 fd sbrc r24, 1 , a ten out, to inicjacja stosu jaka nastepuje w procach avr.

OKi, nie można uzywać zmiennych rejestrowych, i to będzie ta odpowiedź, nie doczytałem sie tego niestety, musze poprzewertować jeszcze mana.

Ten kod jest poprawny ... ale z punktu widzenia kompilatora, a nie z punktu widzenia programu i zawartych w nim danych o przypisaniu zmiennej do rejestru.

Bo po to przypisuje zmienna do rejestru zeby była przypisana, a nie po to żeby kompilator twierdził że on lepiej wie po co tą zmienna przypisuje.

Juz sie wypowiadałem dlaczego nie chce tam volatile.

W takim razie nie ma sensu przypisywania zmiennych do rejestrów. To po co to jest?
Back to top
   
Google

Google Adsense


Post# Post from the author of the topic 12 Apr 2007 11:57   





Back to top
   
szelus
Poziom 20
Poziom 20


Joined: 12 Jul 2004
Posts: 1016

Post#10 12 Apr 2007 14:49helpful post - solution   

Re: call-clobbered register


trol.six wrote:
Niestety musze cie zmartwić , ale jest to kod bezpośrednio przekopiowany z kompilacji. Kod if jest tutaj 268: 81 fd sbrc r24, 1 , a ten out, to inicjacja stosu jaka nastepuje w procach avr.

Ok, no może nie przyjrzałem sie zbyt dokładnie, a z tym out-em faktyczie AVR-gcc tak ma.
Cóż, przeczytaj sobie ten wątek http://gcc.gnu.org/ml/gcc-patches/2005-11/msg00657.html.
Wygląda, że póki co, jest to ograniczenie gcc.
[/url]
Back to top
   
trol.six
Poziom 20
Poziom 20


Joined: 29 Oct 2005
Posts: 1086
Location: Krakow

Post#11 Post from the author of the topic 12 Apr 2007 16:46   

Re: call-clobbered register


No wiec wszystko jest jasne, kompilator traktuje moja zmienna rejestrowa jak inna zmienna i ją optymalizuje po swojemu, brak volatile przed zmienną jest wynikiem niechęci kompilatora przed traktowaniem zmiennej rejestrowej w ten sposób.

Niby sie ma to zmienić, post o zmianie jest z 2005-11 z obietnicą że wersja gcc 4.2 będzie miała te zmiany i nasza zmienna będzie miała status volatile.

Zobaczymy :)
Back to top
   
Post new topic  Reply to topic      Main Page -> Forum Index -> Programming Generally -> call-clobbered register, opce optymalizacji gcc.
Page 1 of 1
Similar topics
[Atmega16][C] Program działa tylko bez optymalizacji kodu (8)
poziomy optymalizacji kodu w WinAvr (3)
[stm32][C] Vector Table Offset Register, NVIC_SetVectorTable (13)
attiny2313 + led 7-seg + shift register (3)
Timer/Counter Register TCNT2 ATmega 16 (2)
[GCC] -Os - czyli jak zrobic, zeby gcc nie zjadalo funkcji? (10)
Algorytmy optymalizacji (rozkroju, cięcia, nestingu) praca inż. (7)
[STM32][Keil][C]Hard Fault tylko przy optymalizacji -O3 (9)

Page generation time: 0.181 seconds


FAQ || Administrator || Moderators || Widgets and banners || Contact
elektroda.pl topic RSS feed