Hi, bin hier grad über eine merkwürdige Sache gestolpert. Folgendes simple Programm: #include <avr/io.h> int main(void) { DDRB = 0xff; while(1) { PORTB=0x00; PORTB=0xff;; } } Erzeugt bei Opt = -O2 folgenden ASM Code while(1) { PORTB=0x00; 9a: 18 ba out 0x18, r1 ; 24 PORTB=0xff;; 9c: 88 bb out 0x18, r24 ; 24 9e: 18 ba out 0x18, r1 ; 24 a0: 88 bb out 0x18, r24 ; 24 a2: fb cf rjmp .-10 ; 0x9a D.h. er verdoppelt das ganze was auch am Oszi zu sehen ist. Bei Opt = -O1 oder -Os macht er es richtig. while(1) { PORTB=0x00; 9a: 18 ba out 0x18, r1 ; 24 PORTB=0xff;; 9c: 88 bb out 0x18, r24 ; 24 9e: fd cf rjmp .-6 ; 0x9a Will jetzt nicht kleinlich sein, bin aber neugierig warum...
Ist doch völlig korrekt. -O2 optimiert auf Laufzeit, -Os auf Platz. Google mal nach "loop unrolling".
Naja, korrekt ist es schon, aber den Inhalt einer while(1)-Schleife einfach zu verdoppeln erscheint mir etwas... beliebig.
Wird schneller dadurch, weil ein Sprung eingespart wird. Dass Microcontroller so bisweilen stolpernde Takte erzeugen - je nun, das ist GCC sowas von egal. Probier das mal mit einer 100-er Schleife, da wird dann evtl. der Inhalt verdoppelt aber die Anzahl Durchläufe halbiert. Von Bedeutung ist das eher bei Standardprozessoren. Denn dort kann diese Optimierung Fliesskomma-Rechenoperationen ein Vielfaches beschleunigen. Deshalb steckt das im GCC drin. Beim AVR ist das ein nur selten erwünschter Nebeneffekt - den man mit irgendeinem -fno-loop-unrolling oder so auch abschalten kann. Generell ergibt alles andere als -Os beim GCC/AVR wenig Sinn.
Ich habe auch schon erlebt, daß der Compiler mit -Os nicht nur langsameren, sondern auch größeren Code als mit -O3 produziert hat, weil er bei -Os scheinbar kein Inlining macht. Makros kann ich nicht einsetzen, da ich mit C++ arbeite und es sich um eine Memberfunktion handelt. Allerdings kann man Funktionen mit __attribute__((always_inline)) ausstatten, was genau das tut, was man erwarten würde. So kann meine C++-Library auch mit -Os optimal übersetzt werden. Inline-Funktionen sind auch sauberer und sicherer als Makros.
Nun, wenn du ihm eine Funktion als inline deklarierst, dann macht er das durchaus auch bei -Os, aber eben nicht immer. Der Compiler versucht eine Abschätzung zu machen, ob das inlining Sinn hat. Es leuchtet ein, dass er sich bei dieser Abschätzung auch mal vertun kann. Was allerdings bei -Os (und wohl auch bei -O2, im Gegensatz zu -O3) wirklich nicht passiert ist, dass der Compiler selbst Funktionen als inline-Code übernimmt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.