Forum: Compiler & IDEs WinAVR-20070122


von Heiko Suesens (Gast)


Lesenswert?

Ich habe soeben ein Update (AVR-Studio 4.13 und WinAVR-20070122) 
durchgeführt und mußte feststellen, das außer mehr Fehlermeldungen 
(../graphic.c:313: warning: pointer targets in passing argument 1 of 
'strncmp_P' differ in signedness) auch der Code enorm größer wird.
Bei mir war die Ausgabe:
vorher  Program:   55052 bytes
nachher Program:   67462 bytes

Dann wollte ich es nun wissen und habe meinen Bootloader neu compiliert, 
siehe da, Er paßt nicht mehr innerhalb von 512 Worten!

Ist das Anderen auch aufgefallen, oder wird nur anders gerechnet, oder 
habe ich etwas übersehen?

von Stefan (Gast)


Lesenswert?

Ja, es wurde schon mehrfach berichtet, dass der AVR-GCC 4.1.1 oft mehr 
Code produziert als die Vorgängerversionen.

U.a. ist ein Teil des Mehrverbrauchs auf einen längeren Prolog/Epilog 
von main() zurückzuführen. Hier kannst du beim Bootloader vielleicht ein 
paar Bytes einsparen.

Ein weiterer wichtiger Unterschied ist IMHO das radikalere 
(Weg-)optimieren von simplen Zählschleifen. Hier sollte man seinen Code 
überarbeiten und die Libraryfunktionen für Delays verwenden.

von Benedikt K. (benedikt)


Lesenswert?

Der GCC 4.1.1 ist schon recht intelligent. Er macht manchmal die 
Fehlersuche anhand des erzeugten Codes recht aufwendig, da der erzeugte 
Code schon ziemlich von dem abweicht was man in C geschrieben hat (aber 
das Ergebnis davon ist gleich).
So erzeugt er zum Beispiel aus diesem Code:
for (i=0; i<8; i++)
 function(i*5);
nicht etwas die Schleife und multipliziert jedesmal, sondern er addiert 
in jedem Schleifendurchlauf 5 hinzu !

Lange habe ich auch gebraucht um folgenden Code zu verstehen:
if ((i>=10)&&(i<15))
{ ... }

subi r18, lo8(10)
sbci r19, hi8(10)
subi r18, lo8(5)
sbci r19, hi8(5)
brsh ...
Auf den ersten Blick erscheind das sinnlos, aber wenn das ganze mal 
genauer durchspielt erkennt man, dass es doch funktioniert.

Der Unterschied zwischen den einzelnen Optimierungsstufen ist auch um 
einiges größer geworden. Die oS Einstellung verwendet z.B. für i/8 nicht 
den Shift, sondern die Divisionsroutine wird aufgerufen, falls diese 
sowiso schon im Code vorhanden ist. Wenn ich genügend Platz im Flash 
habe, verwende ich daher immer o2.

von Peter D. (peda)


Lesenswert?

Also über 12kB mehr ist schon richtig heftig, das liegt definitv nicht 
am längeren Prolog/Epilog.


Mir ist auch aufgefallen, daß er sehr eigensinnig optimiert.

Z.B. inlined er eigenmächtig Funktionen, wenn sie nicht groß genug sind. 
Dadurch hat man sofort den doppelten Codeverbrauch, wenn die Funktion 
nicht static ist.

Leider läßt sich das nur total abschalten, also völliges Verbot, auch 
für Funktionen, die man explizit als static inline deklariert hat.

Er hat den starken Hang für minimalste Zeiteinsparung hohen Mehrcode zu 
erzeugen, was ja eigentlich der Optimierungsstufe -Os völlig 
widerspricht.

Man hätte besser nur die Bugs beseitigen sollen und keine weiteren 
(Un-)Optimierungen einbauen, dann wäre er richtig gut.


Peter


P.S.:
Das mit der Division ist ja nicht der Bringer.
Hoffentlich macht er nicht dann auch aus i>>3 ne Division, das wäre ja 
ein starkes Stück.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger wrote:

> Also über 12kB mehr ist schon richtig heftig, das liegt definitv
> nicht am längeren Prolog/Epilog.

Den Prolog/Epilog von main() sollte man übrigens mittels
__attribute__((noreturn)) los werden können.

> Z.B. inlined er eigenmächtig Funktionen, wenn sie nicht groß genug
> sind.  Dadurch hat man sofort den doppelten Codeverbrauch, wenn die
> Funktion nicht static ist.

Dafür habe ich letztens einen Bugreport aufgemacht.  Unter bestimmten
Umständen werden die internen Kosten für manche Operationen nicht
sauber berechnet.  Der entsprechende Code wird dann zwar auf GCC's
"mainstream" targets (i386, x86_64, ppc) trotzdem noch kürzer, aber
auf dem AVR teilweise länger (was bei -Os ja nicht passieren sollte).

Allerdings ist mir bei der Analyse dieses Bugreports aufgefallen, dass
es für diesen Optimierer natürlich einfach mal tödlich ist, wenn man
in ansonsten kleinen Funktionen ein inline asm statement mit vielen
einzelnen CPU-Befehlen drin hat: das dürfte für die Kostenberechung
als ein Statement betrachtet werden und daher recht schnell ein
Kandidat fürs Inlining werden.

> Leider läßt sich das nur total abschalten, also völliges Verbot,
> auch für Funktionen, die man explizit als static inline deklariert
> hat.

Quatsch.  Natürlich kannst du das auch einzeln abschalten, indem du
die Funktion als __attribute__((noinline)) deklarierst.

> Man hätte besser nur die Bugs beseitigen sollen und keine weiteren
> (Un-)Optimierungen einbauen, dann wäre er richtig gut.

Das ist Quark.  Viele Optimierungen sind einfach völlig neu angegangen
worden im Vergleich zu den 3er Versionen, damit ergeben sich
notwendigerweise neue Nebeneffekte.  Da wir (als AVR-Gemeinde) es nach
wie vor noch nicht geschafft haben, einen Simulator und dessen
Anbindung bereit zu stellen, mit dem die GCC-Leute diese Art von
Regression für unser Lieblingstarget bei ihrer Entwicklungsarbeit
nachvollziehen könnten, ohne dass sie sich mit dem Lötkolben hinsetzen
und selbst AVRs programmieren (sprich: es muss komplett
scriptgesteuert arbeiten und muss natürlich auch
betriebssystemunabhängig sein), können wir uns auch nicht drüber
beklagen, wenn das Ergebnis für uns nicht so ist, wie wir uns das
wünschen.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch wrote:

> Allerdings ist mir bei der Analyse dieses Bugreports aufgefallen, dass
> es für diesen Optimierer natürlich einfach mal tödlich ist, wenn man
> in ansonsten kleinen Funktionen ein inline asm statement mit vielen
> einzelnen CPU-Befehlen drin hat: das dürfte für die Kostenberechung
> als ein Statement betrachtet werden und daher recht schnell ein
> Kandidat fürs Inlining werden.

Ich bin weg von Asm und C mixen, kostet einfach zuviel Arbeitszeit ohne 
wirklichen Nutzen.


> Quatsch.  Natürlich kannst du das auch einzeln abschalten, indem du
> die Funktion als __attribute__((noinline)) deklarierst.

O.k. man kann sämtliche Funktionen editieren, ist aber bei größeren 
Programmen ein heiden Aufwand.
Ich meinte daher einen Schalter, der nur die explizit als inline 
deklarierten Funktionen inlined.

Ich hatte auch bei der alten Version einen krassen Fall, daß eine 
kompletter Funktionsaufruf wegoptimiert wurde. Ich brauchte ein Delay 
von 7 Zyklen (leere Funktion).
Ich mußte erst ein extra Objekt anlegen, dann gings.


> Das ist Quark.  Viele Optimierungen sind einfach völlig neu angegangen
> worden im Vergleich zu den 3er Versionen, damit ergeben sich
> notwendigerweise neue Nebeneffekte.

Interessant zu wissen.
Muß man mal aufpassen, ob sich die 16Bit-Lastigkeit (switch, if) 
verbessert hat.


Peter

von Süsens, Heiko (Gast)


Lesenswert?

Eigentlich wollte ich nur in Erfahrung bringen, ob auch Andere diese 
Beobachtung gemacht haben und ich wollte nicht eine solche Diskussion 
vom Zaune brechen.

@Jörg Wunsch: es ist halt schade, das ich nach einem Update vom Compiler 
meine Programme neu überarbeiten muss, oder evtl. sogar einzelne Teile 
neu schreiben muss.
Ich muss aber auch dem Peter beipflichten, das in der heutigen Zeit mehr 
Wert auf Neuerungen als auf Fehlerbehebung verwandt wird.

Übrigens muss ich auch mein schlechtes Gewissen erleichtern: die Angaben 
der Codegröße resultieren aus keiner Optimierung, also Schalter -O0, 
aber bei beiden Übersetzungen.

Den Prolog/Epilog hatte ich auch schon im Auge, da ich die Zeit eines 
Resets über Watchdog schon auf 30 mSec erhöhen musste, da sonst der 
Prolog nie zum Ende kam und der Watchdog erneut zugeschlagen hatte, aber 
die Untersuchung habe ich noch nicht beendet.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Naja, '-O0' sollte man wohl eher meiden ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger wrote:

> Ich bin weg von Asm und C mixen, kostet einfach zuviel Arbeitszeit
> ohne wirklichen Nutzen.

Nö, nicht zwingend.  Gut aber, ich habe an manchen Stellen mehr den
Blick als avr-libc-Maintainer, da muss man bestimmte Dinge einfach mit
inline asm machen (aber dafür wiederum ist der bei GCC wirklich gut).

> Ich hatte auch bei der alten Version einen krassen Fall, daß eine
> kompletter Funktionsaufruf wegoptimiert wurde. Ich brauchte ein
> Delay von 7 Zyklen (leere Funktion).

Dann nimm dafür keine Funktionsaufrufe, sondern 7 NOPs.

Süsens, Heiko wrote:

> Ich muss aber auch dem Peter beipflichten, das in der heutigen Zeit
> mehr Wert auf Neuerungen als auf Fehlerbehebung verwandt wird.

Trifft gerade für den GCC wirklich nicht zu.  Echte Bugs werden dort
durchaus zügig bearbeitet.  Der AVR-GCC leidet allerdings darunter,
dass es nur sehr wenige Leute gibt, die dort aktiv etwas entwickeln.

von Hans W. (Firma: Wilhelm.Consulting) (hans-)


Lesenswert?

@Jörg Wunsch: was sind denn da die anforderungen an den simulator? Hätte 
da noch ein nettes projektchen an der tu zu machen... vllt passts da 
rein...

das scheint ja irgendwie mit dejagnu zusammenzuhängen.. nur wie genau 
hab ich noch nicht herausgefunden... gibts da irgendwo docu/specs/...??? 
oder darf ich mir mal das ganz aus den cvs holn und dann schaun was 
alles an docu dabei ist?

73

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du kannst mal Eric Weddington fragen, ob er da genaueres weiß, ihn
hatte das Ganze logistisch schon immer interessiert, weil wir mit
einer funktionierenden Anbindung an einen Simulator (und ja, dejagnu)
die Chance hätten, vom "no-name target" sowas wie secondary status
zu bekommen mit dem AVR.  Es gibt wohl schon einen Simulator, den
die ARM-Leute benutzen, und die haben auch genau das geschafft, dass
sie in der ,,Kategorie der Wichtigkeit'' damit aufgestiegen sind.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Was ist denn mit simulavr?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

simulavr ist ungepflegt.  Ich hab' auch keine Ahnung, was das dejagnu-
Zeugs ggf. noch an Voraussetzungen braucht.

von Hans W. (Firma: Wilhelm.Consulting) (hans-)


Lesenswert?

um ostern herum hoff ich mich halbwegs von arbeit befreit zu haben... 
vorausgesetzt es kommt nix neues dazu ;)

werd eric mal nerven g

wär sicher interessant einen vernünftigen simulator zu haben.. ggf mit 
einfacher script-unterstützung für rs232,i2c und spi... ich sollt mir 
mal bei zeiten simulavr anschaun...

73

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Als interaktiver Simulator ist auch GPSIM (GNU PIC simulator)
interessant.  Sein Autor (Scott Dattalo) wäre mehr als interessiert,
wenn jemand diesen auf den AVR portieren würde.

Aber in Obigem geht's um eine reine CPU-Simulation, die aber dafür
bestmöglich mit dejagnu zusammenspielt, vorzugsweise der gleichen
Simulation, die bereits für ARM notwendig ist.

von Wolfgang (Gast)


Lesenswert?

Hallo,

ich habe in einem Projekt (AVR, GCC) an einer Stelle eine 
Inline-Assembler Funktion mit lokalen Sprungzielen verwendet. So weit, 
so gut.

Jetzt habe ich den Compiler auf 20070122 upgedated und bekomme beim 
Übersetzen dieses Moduls die Fehlermeldung:

Error: symbol 'XXX' is already defined.

Dank dieser Diskussion hier ist mir aufgegangen voran es liegt - der 
Compiler hat es inline in den Ausgang gelegt (war mit -Os) übersetzt.

mit Vergabe des Attributs "noinline" gings dann wieder:

void DMXSendByte(uint8_t value) __attribute__((noinline));

Servus Wolfgang

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.