www.mikrocontroller.net

Forum: Compiler & IDEs AVR GCC: Funktion wird weg optimiert... warum?


Autor: digifloh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi @ all,

ich habe ein kleines Problem wo mir ein erfahrener AVR C Programmierer 
bestimmt weiter helfen kann.

Ich rufe folgende Funktion...

void gen_hl() {
  PORTD = 127;
}

...mit...

gen_hl();

...auf.


Solange man den Optimierungs-Schalter auf -O0 (Ohh null) läst geht das 
auch alles. Stellt man um auf -Os was ja empfohlen wird dann ist der 
Optimierer aber fleißig... zu fleißig, er ruft die Funktion erst 
garnicht mehr auf... warum?


Gruß Frank

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!

Es kann sein, dass du in der Klammer auch ein void setzen musst, sonst 
erkennt er es nicht als Funktion
void gen_hl(void) {
  PORTD = 127;
}


MfG

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PORTD als volatile deklariert?

Autor: Joerg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du nachgesehen, ob die Funktion ge"inlined" wird?, d.h. der 
Compiler setzt die Anweisung in der Funktion direkt ins Programm ein, 
anstatt die Funktion aufzurufen.

Autor: digifloh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnellen Antworten,

also (void) bringt nichts, das "komische ist, es läst sich noch nicht 
einmal ein Breakpoint setzen. Deutet wohl darauf hin das er es völlig 
ignoriert.

>> Hast du nachgesehen, ob die Funktion ge"inlined" wird?, d.h. der
>> Compiler setzt die Anweisung in der Funktion direkt ins Programm ein,
>> anstatt die Funktion aufzurufen

Ähm ok, was bedeutet das?
Wo würde man das sehen, was ist zu tun?

Gruß Frank

Autor: Joerg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ähm ok, was bedeutet das?
wenn die Anweisung ausgeführt wird, die in der Funktion steht, ist es 
doch egal.

> Wo würde man das sehen, was ist zu tun?
Sieht man im list-file (da stehen die Assemblerbefehle drin, aus denen 
das Prog im Endeffekt besteht

Autor: digifloh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo ok,

also da sieht es tatsache nicht so aus als ob es angesprungen wird.
Ich verstehe auch ASM, wollte aber nun ein Programm in C schreiben.

Geht das nicht in C das man eben wiederkehrende Sachen in eine Funktion 
legt?

Hmm hat noch jemand einen Tip warum es wohl wegoptimiert wird?

Wie würdet ihr eine Funktion beschreiben?

Das GCC Tour in dem Forum habe ich gesehen, das mache ich eigendlich so.

Verwende AVR Studio und WinAVR.


Gruß Frank'l

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PORTD als volatile deklarieren? Wie geht denn das? ;)
Und was "void" in den Klammern bringen soll, ist mir auch schleierhaft. 
Warum sollte er den Ausdruck nicht als Funktion erkennen?

Woher nimmst du die Information, dass die Funktion nicht aufgerufen 
wird?

PS: Schau doch mal in dem Listfile (*.lst) nach, ob die Funktion 
aufgerufen/inlined wird.

Autor: Joerg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Hmm hat noch jemand einen Tip warum es wohl wegoptimiert wird?
weil der AUfruf (Rcall + push(evtl.) + ... pop + ret) länger 
dauert("teurer ist") als die eigentlich Funktion (ldi + out), wenn du 
eine längere Funktion schreibst oder die Funktion in eine andere 
"compilation-Unit" (.c-Datei) auslagerst, wird die nicht ge-"inlined".

Autor: antworter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da PORTD garantiert als "volatile" deklariert ist, wird es gcc mit 
Sicherheit nicht wegoptimieren.

Wenn es Dir im ASM-Quelltext nicht über den Weg läuft, hast Du es 
bestimmt übersehen...

Probiere doch einfach mal, so ein minimal-Programm zu flashen, um Dir 
dann den PORT über ein Oszi anzuschauen.

Wenn es dann nicht geht, hat Dein uC vielleicht gar keinen PORTD (kommt 
gerne mal vor, daß soetwas übersehen wird)...

Autor: *.* (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Inline bedeutet, dass anstatt "call gen_hl" der Inhalt von gen_hl() 
direkt an dieser Stelle ausgeführt wird. Macht bei einer so kleinen 
Funktion Sinn.

Autor: digifloh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nun ich hab mal den Code auf ein Mininmum reduziert, wie gesagt 
die -O Option ist auf -Os um den "schnellsten" Code zu erzeugen.

gen_off(); Wird nicht angesprungen... :-(

µC ist ein ATmega16 auf'n STK500 mit AVR Studio und WinAVR.


#include <stdlib.h> 
#include <avr/io.h>
#include <avr/interrupt.h>

volatile struct {
   unsigned bGen:1;
   unsigned bActLevel:1;
} fA1;



ISR(TIMER0_OVF_vect)
{
  if bit_is_set (PORTB,PIN0) { PORTB &= ~(1 << PIN0);}
              else { PORTB |=  (1 << PIN0);}
}



void gen_off(void) {
  PORTD = 127;
  fA1.bGen = 0;
}



int main (void) {
//--- PORT B ---
  DDRB  = 0xFF;            // PortD Datenrichtung setzen
  PINB  = 0;              // Pullups off
  PORTB = 0xFF;

//--- PORT D ---
  DDRD  = 0xFF;            // PortD Datenrichtung setzen
  PIND  = 0;              // Pullups off
  PORTD = 0xFF;

//--- Timer 0 ----------------------------------------------------------------
  TIMSK |= (1 << TOIE0);         // Interupt für Timer0 einschalten
  TCCR0 |= (3<<CS00);          // Vorteiler für T/C0 (3=CLOCK/64)

  gen_off();

  sei();

  while(1) {
  }
  return 0;
}

Autor: Mark .. (mork)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo digifloh,

zeig doch mal die .lst-Datei. Bestimmt ist die Funktion in diesem Fall 
geinlined worden, weil es dann einfach schneller geht. Solange die 
Wirkung aber diesselbe ist, sollte es eigentlich egal sein, ob die 
Funktion angesprungen wird oder nicht. Übrigens: -0s erzeugt nicht den 
schnellsten sondern den kleinsten Code. -03 erzeugt den schnellsten 
Code, in den meisten Fällen aber auch den größten.

MfG Mark

Autor: Joerg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meinst du nicht, dass das ein bischen an den Haaren herbeigezogen ist, 
das Programm, das du gepostet hast tut (im Simulator) genau was es soll, 
PORTD wird vorher schon gesetzt, und die struct wird extra gesetzt.
 Demnach meint der gcc dass sich der Aufruf nicht rechnet (da hat der 
sicher recht).
 Du hast eine bessere chance eine Funktion zu beobachten wenn diese 
Parameter übernimmt oder werte zurückgibt. (und es gibt ein no_inline_ 
oder so änhlich -attribute und enstprechende GCC-Parameter, um die zu 
nutzen müsstest du allerdings das GCC-Manual lesen ...

hth. Jörg

Autor: Tishima (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich weis zwar nicht was fuer ein Prozessor es ist, aber das kommt mit 
spanisch vor......


PINB  = 0;              // Pullups off

Ich denke die Zeile tut nicht das was als Kommentar da steht....


gruß,
Bjoern

Autor: let (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das letzte Programm mal durch den gcc gejagt.
'gen_off()' wird ge-inlined, die Funktion selbst ist
aber da. Sie wird halt nur nicht aufgerufen.
Die Funktion muß der Compiler auch erzeugen weil er nicht
wissen kann ob sie nicht von einem anderen Modul aus
aufgerufen wird.

Mit 'static' deklariert nimmt er sie aber raus.

Da habe ich gerade etwas dazugelernt: Ich dachte bisher immer
das der gcc nur mit -O3 inlining benutzt - abgesehen von statischen
Funktionen die nur einmal verwendet werden. Mit -O{0,1,2} wird die
Funktion aufgerufen.

 - Michael

Autor: digifloh (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Jorg X.

Sicher ist es ein Programm was nur als Beispiel dient aber nicht 
unnöglich ist.
Beim START möchte ich einmal die Funktion aufrufen, das ist alles, ich 
gehe mal davon aus das es total egal ist was man da reinschreibt in der 
Funktion. Ob nun 150 ein A über den UART ausgegeben wird oder einfach 
nur der Wert 127 am PortD.

Kann es an meiner Timer Ini liegen?


Die lss Datei hab ich mal angehangen...


MfG Frank'l

Autor: Joerg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist nicht egal, was in der Funktion drinsteht, solange der Compiler 
das weiß! -> wenn du die Funktion in eine andere .c-Datei schreibst, 
wird die auch aufgerufen, weil der Compiler nicht inlinen kann, und 
glaub mir, wenn inlinen keine Vorteile bringt wird der compiler es auch 
ganz lassen.

Können wir diese "Diskussion" fortsetzen, falls der GCC so inline't, 
dass das Programm nicht mehr funktioniert?

Autor: digifloh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@Joerg X.
Ja war vlt. etwas übertrieben, ich wollte nur sagen das es für das 
Verständniss Funktionen halt egal wäre was im eigendlichen in ihr steht.

Vielleicht wäre eine For Schleife besser... ;)

Ok Knackpunkt ist das inline, das wußte ich nicht.
Ich habe nun mal das prg Step für Step im Deassembler durchgeklickert... 
es macht inline wie du richtig angenommen hast...

Also muß mein Fehler woanders liegen, ich hab was gelernt und sogar 
verstanden was :-D

Das nächste mal wenn sich ein Punkt nicht anspringen läst schau ich hier 
als erstes nach.

Dank euch... schönen Sonntag...

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ok Knackpunkt ist das inline, das wußte ich nicht.

Der Knackpunkt ist nicht das inline, sondern, daß der gcc, genauso, wie 
andere Compiler auch, bei eingschalteter Optimierung Code erzeugt, der 
nicht mehr 1:1   rückwärts dem C-Quelltext zugeordnet werden kann. Das 
macht der nicht nur durch inlining, da gibt es noch viele andere 
"Schweinereien" :-)

Fazit:
Wenn du deinen Sourcecode Zeile für Zeile durchsteppen möchtest, geht 
das nur mit -O0. Andere Compiler verbieten von vorherein, Debuginfos für 
optimierte Programme zu erzeugen, der gcc ist da etwas großzügiger.

Oliver

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.