Forum: Compiler & IDEs Seltsames Compilerergebnis


von JarJar (Gast)


Lesenswert?

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...

von A.K. (Gast)


Lesenswert?

Ist doch völlig korrekt. -O2 optimiert auf Laufzeit, -Os auf Platz.

Google mal nach "loop unrolling".

von JarJar (Gast)


Lesenswert?

Ok, danke. Wieder was gelernt :)

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Naja, korrekt ist es schon, aber den Inhalt einer while(1)-Schleife
einfach zu verdoppeln erscheint mir etwas... beliebig.

von A.K. (Gast)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.