mikrocontroller.net

Forum: Compiler & IDEs avr-gcc verdoppelt code von Funktionsaufruf


Autor: Andreas Kielkopf (andreasbw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich hab heute wieder angefangen etwas mit dem ATTINY2313 zu basteln. 
Weil ich wenig Erfahrung mit C auf Mikrocontrollern hab, schau ich mir 
immer etwas genauer an, was der Compiler aus meinem C-Code macht. Das 
hilft mir einfach bei der Fehlersuche. Manchmal vergleiche ich auch, 
welche Variante eines Ausdrucks dabei den kleineren Code erzeugt.

Dabei hab ich festgestellt, daß bestimmte Programmteile dopplet im Code 
vorkommen.

Ich versteh nur nicht warum !

Die folgende Variante erzeugt ein 124 Byte langes Programm
----
#include "avr/io.h"
#include "avr/portpins.h"

static void init_display() {
  DDRA|= _BV(PD1) | _BV(PD0);
  DDRA|= _BV(PD1);
  DDRA|= _BV(PD0);
  DDRB|= _BV(PD2) | _BV(PD3) | _BV(PD4);
  PORTB= _BV(PD2) | _BV(PD3) | _BV(PD4);
  DDRD|= _BV(PD0) | _BV(PD1) | _BV(PD2) | _BV(PD3) | _BV(PD4) | _BV(PD5);// + P6;
}

// void init() { init_display(); }

int main(void) {
  init_display();
  //init();
  while (-1)
    asm("nop");
}
----
Schachtle ich das Unterprogramm eine Ebene tiefer, so erzeugt der gcc 
ein 152 Byte langes Programm
----
#include "avr/io.h"
#include "avr/portpins.h"

static void init_display() {
  DDRA|= _BV(PD1) | _BV(PD0);
  DDRA|= _BV(PD1);
  DDRA|= _BV(PD0);
  DDRB|= _BV(PD2) | _BV(PD3) | _BV(PD4);
  PORTB= _BV(PD2) | _BV(PD3) | _BV(PD4);
  DDRD|= _BV(PD0) | _BV(PD1) | _BV(PD2) | _BV(PD3) | _BV(PD4) |
_BV(PD5);// + P6;
}

void init() { init_display(); }

int main(void) {
  //init_display();
  init();
  while (-1)
    asm("nop");
}
----
Dabei ist dann der Code für init_display() doppelt vorhanden

Was mache ich falsch ?
Andreas

avr-gcc -Wall -g2 -gstabs -Os -fpack-struct -fshort-enums -std=gnu99 
-funsigned-char -funsigned-bitfields -v -mmcu=attiny2313 
-DF_CPU=8000000UL -MMD -MP -MF"main.d" -MT"main.d" -c -o"main.o" 
"../main.c"

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt eine Option -fwhole-program oder so ähnlich; damit vermute
ich ist der Effekt weg.

Autor: Ansgar K. (paulderbademeister)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Fall: Unterfunktion ist static, darf geinlined und wegoptimiert 
werden
2. Fall: Unterfunktion ist nicht stativ, daher wird geinlined aber nicht 
wegoptimiert, da es unbekannte aufrufe geben könnte

=> zweite Unterfunktion auch static machen und nochmal testen

Autor: Andreas Kielkopf (andreasbw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ansgar K. schrieb:
> 1. Fall: Unterfunktion ist static, darf geinlined und wegoptimiert
> werden
> 2. Fall: Unterfunktion ist nicht stativ, daher wird geinlined aber nicht
> wegoptimiert, da es unbekannte aufrufe geben könnte
>
> => zweite Unterfunktion auch static machen und nochmal testen

Volltreffer !!!
Schachtelungstiefe(St) 1/2

beide Funktionen nicht static:
(St) -O0, -O1, -O2, -O3, -Os
  1  200  144  124  124  124
  2  216 <148> 152  152  152

eine Funktion static:
(St) -O0, -O1, -O2, -O3, -Os
  1  200  144  124  124  124
  2  216 <148> 152  152  152

beide Funktionen static:
(St) -O0, -O1, -O2, -O3, -Os
  1  200  144  124  124  124
  2  216  144  124  124  124
----
Hab was gelernt: statische Funktionen lassen sich problemloser 
optimieren.

Trotzdem ist es komisch, daß die Optimierung -O1 in 2 Situationen besser 
abschneidet als -Os

Andreas

Autor: Rolf Magnus (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Kielkopf schrieb:
> Hab was gelernt: statische Funktionen lassen sich problemloser
> optimieren.

Naja, wenn eine Funktion nicht statisch ist, muß der Compiler davon 
ausgehen, daß sie noch von wo anders aus aufgerufen werden könnte. Er 
führt sie dann innerhalb dieser Übersetzungseinheit inline aus, 
generiert aber zusätzlich eine nicht-inline-Version für den Aufruf von 
außen.

Autor: Ansgar K. (paulderbademeister)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hier nochmal ein kurzer Nachtrag, mein letzter Beitrag war auf nem 
Smartphone getippt und daher kurz gehalten. Rolf hat mir den Großteil 
schon abgenommen und nochmal erklärt was static in diesem Fall für einen 
Unterschied macht.

Das "schlechtere" Ergebnis der höheren Optimierungsstufen liegt daran, 
dass -O1 kein inlineing betreibt. Die höhere Optimierungsstufen nutzen 
dies und produzieren dadurch zwar minimal längeren Code, der aber 
schneller ist und keinen Platz auf dem Stack verbraucht. Erst das 
static, das die Löschung der nicht-inline-Version erlaubt, macht 
inlineing durch die Bank besser.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.