Forum: Compiler & IDEs Minimalbeispiel zur Darstellung effizienter Schleifen


von essence (Gast)


Lesenswert?

Nabend,

ich versuche mich gerade an einem Minimalbeispiel:
1
#include <avr/io.h>
2
int main(void) {
3
  uint8_t i, n;
4
  for (i=0; i<17; i++) {
5
    n++;
6
  }
7
}

Daraus wird allerdings im .lss:
1
int main(void)
2
{
3
  b4:  80 e0         ldi  r24, 0x00  ; 0
4
  b6:  90 e0         ldi  r25, 0x00  ; 0
5
  b8:  08 95         ret
6
7
000000ba <_exit>:
8
  ba:  f8 94         cli
9
10
000000bc <__stop_program>:
11
  bc:  ff cf         rjmp  .-2        ; 0xbc <__stop_program>

Ich nehme an, dass durch das Makefile irgendwelche Optionen aktiviert 
werden, die die Schleife eliminieren.
Könnte das jemand bei sich testen oder mir ein Makefile mit 
funktionierenden Optionen zukommen lassen?

von Sven P. (Gast)


Lesenswert?

Ja, Schleife ist sinnlos -> weg damit. Macht quasi jeder optimierende 
Übersetzer so.

Für GCC: Option -O0 (Oh-Null).

von essence (Gast)


Lesenswert?

Das habe ich mir fast gedacht. Danke.

von Rolf Magnus (Gast)


Lesenswert?

Es scheint mir aber irgendwie sinnfrei zu sein, zu untersuchen, wie eine 
effiziente Umsetzung einer Schleife durch den Compiler aussieht, wenn 
man dabei Optimierungen ausschaltet.
Der Beispielcode ist natürlich ähnlich sinnfrei, da einerseits n einen 
undefinierten Wert hat, andererseits ein 17maliges Inkrementieren von n 
das gleiche ist wie n += 17. Dazu kommt dann noch, daß weder i noch n 
für irgendwas verwendet werden, also optimiert der Compiler kurzerhand 
einfach alles komplett weg. So gesehen gäbe es keine Möglichkeit, die 
Schleife noch effizienter umzusetzen, als es der Compiler getan hat. ;-)

von Uwe .. (uwegw)


Lesenswert?

Noch effizienter (allerdings nicht mehr standardkonform, GCC macht es 
aber trotzdem) wird es, wenn du den Rückgabetyp von main() auf void 
änderst. Dann hast du eine Funktion, die nichts macht, was irgendwas 
außerhalb von ihr bewirkt, und die nichts zurückgibt. Ergebnis der 
Optimierung:
ret
Effizienter geht es kaum noch, man könnte nur noch inlinen und sämtliche 
Aufrufe von main() rauschmeißen [was aber wohl kein Compiler machen 
würde, weil ne leere Main ja nicht gerade üblich ist]... Und wenn main() 
dann also nie aufgerufen wird, dann könnte man auch den Startup-Code 
weglassen... somit bleibt nicht übrig...

von Mark B. (markbrandis)


Lesenswert?

1.) Meckert der Compiler nicht über die fehlende return-Anweisung?

2.) Bei z.B. einem return n; dürfte der Compiler die Variable nicht so 
einfach wegoptimieren? Sonst zieht er sich ja den Rückgabewert unter den 
Füßen weg ;o)

von Rolf Magnus (Gast)


Lesenswert?

> 2.) Bei z.B. einem return n; dürfte der Compiler die Variable nicht so
> einfach wegoptimieren? Sonst zieht er sich ja den Rückgabewert unter den
> Füßen weg ;o)

Er muß in diesen Zeilen
1
 b4:  80 e0         ldi  r24, 0x00  ; 0
2
  b6:  90 e0         ldi  r25, 0x00  ; 0

einfach die 0 durch den Wert, den n nach der Schleife hätte, ersetzen.

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


Lesenswert?

Rolf Magnus schrieb:

> Er muß in diesen Zeilen
> einfach die 0 durch den Wert, den n nach der Schleife hätte, ersetzen.

Da n einen undefinierten Anfangswert hat, ist 0 ein absolut korrekter
return-Wert. ;-)

von jozi59 (Gast)


Lesenswert?

Zumal n auch überhaupt nicht als return value verwendet wird. Es wird 
nämlich überhaupt kein return value angegeben. :-)

von Rolf Magnus (Gast)


Lesenswert?

>> Er muß in diesen Zeilen einfach die 0 durch den Wert, den n nach der
>> Schleife hätte, ersetzen.
>
> Da n einen undefinierten Anfangswert hat, ist 0 ein absolut korrekter
> return-Wert. ;-)

Allerdings. Das wollte ich eigentlich nicht weiter ausführen. Rein aus 
Interesse habe ich aber mal geschaut, was der Compiler denn tatsächlich 
daraus macht, und er entscheidet sich dafür, n wie mit 0 initialisiert 
zu behandeln, schreibt also einen Rückgabewert von 17 in die Register.

@jozi59:

> Zumal n auch überhaupt nicht als return value verwendet wird.

Vielleicht liest du besser nochmal nach, worauf ich geantwortet hatte.

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.