avr-gcc verdoppelt code von Funktionsaufruf

OP #2003985
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
----
1
#include "avr/io.h"
2
#include "avr/portpins.h"
3

4
static void init_display() {
5
  DDRA|= _BV(PD1) | _BV(PD0);
6
  DDRA|= _BV(PD1);
7
  DDRA|= _BV(PD0);
8
  DDRB|= _BV(PD2) | _BV(PD3) | _BV(PD4);
9
  PORTB= _BV(PD2) | _BV(PD3) | _BV(PD4);
10
  DDRD|= _BV(PD0) | _BV(PD1) | _BV(PD2) | _BV(PD3) | _BV(PD4) | _BV(PD5);// + P6;
11
}
12

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

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

4
static void init_display() {
5
  DDRA|= _BV(PD1) | _BV(PD0);
6
  DDRA|= _BV(PD1);
7
  DDRA|= _BV(PD0);
8
  DDRB|= _BV(PD2) | _BV(PD3) | _BV(PD4);
9
  PORTB= _BV(PD2) | _BV(PD3) | _BV(PD4);
10
  DDRD|= _BV(PD0) | _BV(PD1) | _BV(PD2) | _BV(PD3) | _BV(PD4) |
11
_BV(PD5);// + P6;
12
}
13

14
void init() { init_display(); }
15

16
int main(void) {
17
  //init_display();
18
  init();
19
  while (-1)
20
    asm("nop");
21
}
----
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"
OP #2004286
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
#2005622
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.
#2006799
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

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.