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?
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.
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.
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.
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.
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
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.
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.
@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
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.
simulavr ist ungepflegt. Ich hab' auch keine Ahnung, was das dejagnu- Zeugs ggf. noch an Voraussetzungen braucht.
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.