mikrocontroller.net

Forum: Compiler & IDEs GCC 4.1.1. schlechte Optimierung


Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anbei ein Beispiel (ist ne Funktion aus meinem Jumbo-LED Beispiel), wo
der GCC 4.1.1. schlecht optimiert.


Zuerst wird eine 16Bit-Variable komplett gelesen, obwohl nur das
High-Byte gebraucht wird (die Version 3.4.6. konnte das aber schon
optimieren).

Dann wird eine Funktion ge-inlined, obwohl sie nicht static ist und mit
-Os auf size optimiert werden soll.

Dann wird ein großes Codestück dupliziert (im test411.lst hinter der
RET-Zeile) nur um ein "ldi r28, 0x00" einzusparen.


Hier mal die Statistik:

4.1.1
   text    data     bss     dec     hex filename
    296      10       8     314     13a test.out

3.4.6
   text    data     bss     dec     hex filename
    236      10       8     254      fe test.out

Sind also beeindruckende 25% mehr mit dem 4.1.1.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch was vergessen, die Kommandozeile:


avr-gcc.exe -xc -Os -mmcu=attiny26 -Wall -g disptime.c


Peter

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wobei man aber dazu sagen sollte, dass der neue GCC meistens besser
optimiert als der alte.
Zumindest von der Geschwindigkeit her ist der vom 4.1.1 erzeugte Code
fast immer etwas besser.
Anscheinend inlined der 4.1.1 alle Funktionen die eine bestimmte Größe
unterschreiten. Hier ist die Funktion halt so klein, dass eine Funktion
eigentlich keinen Sinn macht.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Benedikt,

was soll denn inlinen für einen Sinn machen, wenn die Funktion nicht
static ist ?

Er muß sie ja trotzdem stehen lassen, da sie von woanders aufgerufen
werden könnte. Wenigstens tut er das auch.

Das Inlinen an der Größe festzumachen ist der falsche Ansatz, auch die
Anzahl der Aufrufe ist entscheidend.

Der Geschwindigkeitsvorteil hier ist unbedeutend, da ja noch
haufenweise Divisionen drumrum sind. Da verschwindet die Zeit für ein
gespartes Call+RET einfach im Nirwana.

Ich hätte natürlich überhaupt nichts dagegen, wenn der Compiler ein
Division+Modulo optimiert.


Auch sollte bitteschön der -Os Schalter nicht ignoriert werden, d.h.
Größe vor Geschwindigkeit. Also Inlinen nur, wenn ich auch den Schalter
dafür setze.

Ich hab auch die anderen Level ausprobiert -O0...-O3, immer war der
3.4.6.-Code kürzer.


Peter

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> was soll denn inlinen für einen Sinn machen, wenn die Funktion
> nicht static ist ?

C fordert nicht das eine Funktion die geinlined wird static sein
muss.
Ganz im Gegenteil: Auf Nicht-µC ist es eher die Regel, dass sie
es nicht sind. Die übliche Vorgehensweise ist es, diese Funktionen
in Header Files auszulagern und natürlich die Funktion als inline
zu markieren. static macht man die dann aber nicht, da man ansonsten
in jeder Compilation Unit eine neue Kopie der Funktion erzeugt.

> Er muß sie ja trotzdem stehen lassen, da sie von woanders aufgerufen
> werden könnte. Wenigstens tut er das auch.

Yep. Und ein guter Linker schmeist sie dann wieder raus, wenn kein
einziger Aufruf übrig bleibt.

> Das Inlinen an der Größe festzumachen ist der falsche Ansatz, auch
> die Anzahl der Aufrufe ist entscheidend.

Die kann aber der Compiler nicht alle überblicken, da er sich ja
immer nur auf eine Compilation-Unit konzentriert.
Also inlined der was das Zeug hält. Sobald die Funktion klein genug
ist wird sie aufgelöst.

> Der Geschwindigkeitsvorteil hier ist unbedeutend, da ja noch
> haufenweise Divisionen drumrum sind. Da verschwindet die Zeit
> für ein gespartes Call+RET einfach im Nirwana.

Bei allem nötigen Respekt: Aber das kümmert den Compiler einen
feuchten Kehrricht.

> Auch sollte bitteschön der -Os Schalter nicht ignoriert werden,
> d.h. Größe vor Geschwindigkeit. Also Inlinen nur, wenn ich auch den
> Schalter dafür setze.

100% ACK
Das ist mir auch schon mal aufgefallen. Das kann ich mir
eigentlich nur so erklären:
Durch das inlinen eröffnen sich oft neue Optimierungsmöglichkeiten
über die Funktionsgrenzen hinweg. Möglicherweise hat jemand
statistisch herausgefunden, dass sich das im Mittel lohnt und
die zusätzlichen Optimierungen den zunächst größeren Code im
Mittel kleiner kriegen.

Glücklich bin ich auch nicht damit. Ich hätte auch erwartet, dass
bei -Os keine inlines stattfinden.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was das inlinen mit -Os angeht: Das dürfte mit C++ zusammenhängen. Da
sind inlines sehr verbreitet, oft nicht mehr als Zugriffsfunktionen auf
class members. Konsequenter Verzicht auf inlining macht den Code dann
nicht kleiner sondern deutlich grösser.

Im Compiler immer genau die richtige Grenze zu finden, ist allerdings
eine Wissenschaft für sich. Komplexität der Funktion allein ist ein
schwaches Mass, da wie du schon andeutest, Synergien auftreten, die
erst erkannt werden, wenn man die Codegenerierung schon halb durch hat.
Man es aber lieber vorher wüsste ob oder ob nicht.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Apropos: -fno-inlines oder so. Das funktioniert m.W. immer. Nützlich
insbesondere beim Durchsteppen, weil man sonst allzu leicht die
Übersicht verliert.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die kann aber der Compiler nicht alle überblicken, da er sich ja
> immer nur auf eine Compilation-Unit konzentriert.

Bei GCC 4 nicht mehr notwendigerweise, man kann ihm auch mehrere
compilation units gemeinsam vorwerfen.

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.