Forum: Compiler & IDEs Riesencode im List.


von Sven P. (Gast)


Lesenswert?

Huhu,

hab mal folgendes übersetzen lassen:
1
ISR(TIMER2_COMP_vect) {
2
  /* Turn off display */
3
  PORTD = 255;
4
}

Hab mich gewundert, warum die ISR so lahm ist (bin bissi knapp bei 
Resourcen). Im List kam dann raus:
1
 128:  1f 92         push  r1
2
 12a:  0f 92         push  r0
3
 12c:  0f b6         in  r0, 0x3f  ; 63
4
 12e:  0f 92         push  r0
5
 130:  11 24         eor  r1, r1
6
 132:  8f 93         push  r24
7
  /* Turn off display */
8
  PORTD = 255;
9
 134:  8f ef         ldi  r24, 0xFF  ; 255
10
 136:  82 bb         out  0x12, r24  ; 18
11
 138:  8f 91         pop  r24
12
 13a:  0f 90         pop  r0
13
 13c:  0f be         out  0x3f, r0  ; 63
14
 13e:  0f 90         pop  r0
15
 140:  1f 90         pop  r1
16
 142:  18 95         reti

Und da dacht ich mir, das kann doch wohl nicht wahr sein?! Übersetzt 
wurde mit -Os.

Der Schnipsel hier hätte doch genau dieselben Wirkungen und 
Nebenwirkungen:
1
push r16
2
ldi r16, 255
3
out 0x12, r16
4
pop r16
Vorallen Dingen, was zum Geier hat "eor r1, r1" oben zu suchen?

Kann man dem GCC das irgendwie verständlich machen? Ich mein, dass der 
mir ab drei Variablen sowieso fast das ganze Registerfile pusht, daran 
hab ich mich ja gewöhnt, aber sowas?

Vielen Dank und viele Grüße,
Sven

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

Wenn die ISR wirklich so extrem zeitkritisch und simpel ist implementier 
sie doch in einer .s Datei in Assembler und link sie deinem Projekt 
dazu.

Matthias

von Sven P. (Gast)


Lesenswert?

Oder die ISR als Naked darstellen und dann inline-ASM, schon klar. Aber 
was baut der GCC denn da überhaupt fürn "Müll" zusammen?

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

das muss er halt machen da er über den Code in der ISR recht wenig weiß 
bzw. noch niemand den Compiler in diese Richtung optimiert hat.

eor r1, r1 setzt dabei das Zero-Register auf 0 da der Compiler ja nicht 
wissen kann ob eben jenes irgendwo mal nicht 0 war.

Auch der restliche Code hat durchaus seine Bedeutung. Wenn dir das also 
zu viel ist -> .s oder Inline-ASM.

Matthias

von Sven P. (Gast)


Lesenswert?

Ich weiß ja, wozu der Code ist:
1
 ; Zero-Register retten (könnte ja vom MUL benutzt sein
2
 128:  1f 92         push  r1
3
4
 ; Unsinnigerweise r0 retten; retten, weils ja vom LPM benutzt
5
 ; sein könnte. Aber man hätte auch r1 benutzen können.
6
 12a:  0f 92         push  r0
7
8
 ; SREG retten. Warum auch immer hier r0 benutzt wird;
9
 ; r1 hätte es genauso gut getan
10
 12c:  0f b6         in  r0, 0x3f  ; 63
11
 12e:  0f 92         push  r0
12
13
 ; GCC weiß scheinbar net, dass überhaupt keine "0" hier
14
 ; gebraucht wird.
15
 130:  11 24         eor  r1, r1
16
17
 ; ein direktes Register retten
18
 132:  8f 93         push  r24
19
  /* Turn off display */
20
  PORTD = 255;
21
 134:  8f ef         ldi  r24, 0xFF  ; 255
22
 136:  82 bb         out  0x12, r24  ; 18
23
 138:  8f 91         pop  r24
24
25
 ; SREG wieder herstellen
26
 13a:  0f 90         pop  r0
27
 13c:  0f be         out  0x3f, r0  ; 63
28
29
 13e:  0f 90         pop  r0
30
 140:  1f 90         pop  r1
31
 142:  18 95         reti

Hier ist also reichlich gefahrloses Optimierungspotential vorhanden ;-)

von Der A. (der-albi)


Lesenswert?

Ich denke in r0 wird das Status-Register gesichert (keine Ahnung, ob das 
stimmt - loisch wärs aber - man müsste mal das Datenblatt ansehen, was 
der da reinholt) r1 wird auf 0 gesetzt, weil er das Statusregister als 
16-Bit int verwaltet (auch nur Vermutung). Dann nutzt er r24 für das 
ldi.
Alles in allem unschön, aber dennoch nachvollziehbar.

Dein Schnipsel hätte halt wesentlich mehr Nebenwirkungen, wie du es 
nennst, weil du das Statusregister nicht sicherst. Gefährlich!! ;-)

MFG

von Sven P. (Gast)


Lesenswert?

@Albi: Joa, soweit warn wir schon, schätze mal, wir ham gleichzeitig 
getippselt...:-)

Der Albi wrote:
> Ich denke in r0 wird das Status-Register gesichert (keine Ahnung, ob das
> stimmt - loisch wärs aber - man müsste mal das Datenblatt ansehen, was
> der da reinholt)
Er benutzt r0 als temporäres Register, um damit das Statusregister aufn 
Stack zu pushen, jo.

> r1 wird auf 0 gesetzt, weil er das Statusregister als
> 16-Bit int verwaltet (auch nur Vermutung).
Nö; r1 ist per Definition immer als "Nullregister" gedacht. Deshalb 
setzt er es auf Null-.

> Dann nutzt er r24 für das ldi.
> Alles in allem unschön, aber dennoch nachvollziehbar.
Jubb.

> Dein Schnipsel hätte halt wesentlich mehr Nebenwirkungen, wie du es
> nennst, weil du das Statusregister nicht sicherst. Gefährlich!! ;-)
Hätte er nicht. Weder LDI noch OUT noch PUSH noch POP verändern das 
Statusregister. Daran habe ich schon gedacht...

von Simon K. (simon) Benutzerseite


Lesenswert?

Ja, schön und gut. Das "Problem" ist bekannt und wie gesagt hat in der 
Hinsicht noch keiner Hand angelegt am AVR-GCC. Sprich: Es gibt einfach 
keine Optimierungsroutine an dieser Stelle, die überprüft ob das 
Nullregister überhaupt gebraucht wird oder ob das SREG überhaupt 
verändert wird.

Und für die 10 (über den Daumen gepeilt) Takte wird sich da so leicht 
wahrscheinlich auch niemand für begeistern lassen.

Man sollte auch nicht ausschließen, dass vielleicht irgendwelche Normen 
im C-Compilerbau bestimmte Sachen einfach verbieten. Dazu müsste sich 
aber einer der Compiler-Freaks hier mal zu Wort melden ;)

PS: Was spricht gegen eine naked-ISR und einem kleinen C-Kommentar an 
der Stelle, dass es legitim ist?

von G. L. (sprintersb)


Lesenswert?

Simon K. wrote:
> Sprich: Es gibt einfach keine Optimierungsroutine an dieser Stelle,
> die überprüft ob das Nullregister überhaupt gebraucht wird oder ob
> das SREG überhaupt verändert wird.

Der Haken ist, dass die Änderungen im avr-gcc weit über "diese Stelle" 
hinausgingen.

In r1 steht in avr-gcc immer die 0. Dies geschieht jedoch komplett 
implizit, d.h. gcc hat keine Vorstellung davon. Das ist auch der Grund, 
warum Instruktionen (insns), welche r1 verändern (zB mul) r1 immer 
wieder von Hand herstellen müssen und r1 nicht in der 
Register-Allokierung teilnimmt.

Ich wüsst auch garnicht, wie das gcc beizubringen wäre, d.h welches RTL 
das ausdrücken könnte. Dazu müsste man nämlich sagen können, dass in 
einem bestimmten GPR ein bestimmter Wert vorhanden sein muss. Evrl 
könnte man in jedem Prolog ein (set (reg) (const_int 0)) emittieren und 
mit (use (reg)) die Verwendung anzeigen. Allerdings führt das an anderen 
Stellen zu Problemen, die ohne weiteres nicht zu beheben sind.

Mit SREG sieht's da schon einfacher aus, weil avr-gcc den CC (Condition 
Code) implementiert und jede Insn enstprechend attribuiert.

Also los Jungs, wenn ne hausbackene naked-ISR zu viel Arbeit ist, ihr 
wisst wo die Quelle ist ... feel free to improve and contribute to 
GCC...

von Sven P. (Gast)


Lesenswert?

Hihi, ne, dass das so tief verstrickt ist, dass wusst ich auch noch 
nich. Najo, irgendwann vielleicht mal^

Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.