Forum: Compiler & IDEs GCC inlined die ganze Zeit meine Funktionen.


von Matthias L. (matze88)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich habe gerade ein Problem mit meinem GCC, Version ist das neuste 
WinAVR (vom Juni).
Und zwar meint er trotz Optimierung -Os häufig Funktionen inlinen zu 
müssen, auch wenn das aus meiner Sicht völlig schwachsinnig / 
verschwenderisch ist. Gibt es ein Keyword, um dem Compiler zu sagen, 
dass diese Funktion immer explizit aufgerufen werden soll? Ich kann ja 
schlecht für jede Funktion ein eigenes C-File machen :-)

Ein Beispielcode:
1
char pgmInitSirfMode[] PROGMEM = "\x1b" "$PSRF100,0,38400,8,1,0*3C\r\n";
2
3
void gps_enable (void)
4
{
5
  PRR &= ~(1 << PRUSART0);
6
  UBRR0 = GPS_UBRRVAL;
7
  UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
8
  FETPORT &= ~(1 << GPS_FET);
9
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
10
  gps_transmit_p(pgmInitSirfMode);
11
}
12
13
void gps_transmit (uint8_t byte)
14
{
15
  while (! (UCSR0A & (1 << UDRE0)));
16
  UDR0 = byte;
17
}
18
19
void gps_transmit_p (PGM_P address)
20
{
21
  uint8_t count = pgm_read_byte(address++);
22
  while(count--)
23
  {
24
    gps_transmit(pgm_read_byte(address++));
25
  }
26
}

Das generierte Listing für den Abschnitt ist im Anhang.
Kurz beschrieben: Er inlined einmal die gps_transmit_p und dortdrin auch 
noch den gps_transmit Aufruf. Somit vergeudet der liebe GCC alleine an 
dieser Stelle etliche Bytes Flash, ohne gezählt zu haben sind das 
sicherlich ~30.

Das gleiche Problem hatte ich mit meiner Init() Funktion, welche zu 
Beginn der Main aufgerufen wird. Das Problem habe ich gelöst, indem ich 
sie einfach als inline deklariert habe, sodass er sie nicht nochmal als 
aufrufbare Funktion ins Flash packt. Das ist aber eher ein work-around 
und geht nicht immer... Warum "optimiert" er denn bei -Os nicht wirklich 
auf kleinen Code? In diesem Fall hier wäre der Geschwindigkeitsverlust 
durch den call sehr marginal im Vergleich zur sowieso benötigten 
Ausführungszeit...

Was mache ich falsch? :-)

cu
Matze

von Freizeitbastler (Gast)


Lesenswert?

Hi Matze

ich fange gerade erst an mit WinAVR. Im Allgemein lässt sich für C aber 
sagen: Wenn Du die Funktionen in getrennte Quelldateien packst wird der 
Compiler nicht mehr inlinen.

Ob das Inlinen hier wirklich schlecht ist, wäre ich mir nicht so sicher. 
Da können die Experten sicherlich etwas zu sagen.

Gruß, Peter

von Johannes M. (johnny-m)


Lesenswert?

Versuch es einfach mal mit
1
__attribute__((noinline))
in der Funktionsdefinition.

von Andreas K. (a-k)


Lesenswert?

-fno-inline
-fno-inline-small-functions

von Matthias L. (matze88)


Lesenswert?

Ahh, sehr gut :-) Habt vielen Dank für eure Antworten. Ich verstehe zwar 
noch nicht so ganz, warum der Compiler da meiner Meinung nach suboptimal 
arbeitet, aber der kann ja auch eigentlich nicht wissen, wie die 
Laufzeit der Funktion dann wirklich ist. Ich freu mich jetzt jedenfalls 
über gesparte 150 Bytes Flash :-)

cu
Matze

von Εrnst B. (ernst)


Lesenswert?

> Ich verstehe zwar
> noch nicht so ganz, warum der Compiler da meiner Meinung nach suboptimal
> arbeitet, aber der kann ja auch eigentlich nicht wissen, wie die
> Laufzeit der Funktion dann wirklich ist.

Naja, deine Funktionen sind ja sehr kurz, und eigentlich ideale 
Kandidaten fürs Inlining.
Scheinbar gefällt dem GCC das inlining hier sogar so gut, dass er es 
trotz -Os macht (Gibts sicher einen Parameter mit dem man das 
feineinstellen kann)

Und nachdem die Funktionen nicht als "static" deklariert sind, muss er 
sie halt ein zweites mal, für den Aufruf aus anderen C-Files heraus, in 
das Object-File compilieren.

Edit:
 `-finline-limit=N' Scheint die richtige GCC-Stellschraube zu sein...

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.