Minimalbeispiel zur Darstellung effizienter Schleifen

Gast #1529195
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?
Gast #1529211
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. ;-)
#1529228
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...
Gast #1529443
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.
Gast #1529466
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren