Embedded AVR erzeugt seit Neuestem ineffizienten Code

Rund um die LCL und andere Komponenten
Antworten
Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von Timm Thaler »

Ich musste leider beim Blick in die aktuellen Compiler-Listings feststellen, dass der Compiler für AVR Embedded dazu übergegangen ist ineffizienten Code zu erzeugen. Zum Beispiel:

Multiplikation
- Es werden an vielen Stellen, wo früher die nativen mul Befehle des Controllers verwendet wurden 8- und 16bit Variablen auf 32bit aufgebläht und eine Funktion fpc_mul_dword aufgerufen.

Enumerations
- Es werden auch bei Aufzählungen mit einstelliger Anzahl 32bit-Variablen angelegt, und man muss den Compiler mit {$PACKENUM 1} zur Verwendung von Bytes zwingen. Laut Beschreibung sollte der Compiler immer die kleinstmögliche Variable verwenden.

Vergleiche
- Es werden bei Vergleichen mit 16bit-Varibalen, die überlaufen könnten, alle Variablen auf 32bit erweitert, und die Vergleiche entsprechend aufwendiger.

Code: Alles auswählen

        if aaa > bbb + 10 then begin ...


mit aaa, bbb als uint16 wird zu

Code: Alles auswählen

   lds   r22,(U_sPsTEST_ss_BBB)
   lds   r23,(U_sPsTEST_ss_BBB+1)
   mov   r20,r1
   mov   r21,r1
   ldi   r18,40
   add   r22,r18
   adc   r23,r1
   adc   r20,r1
   adc   r21,r1
   lds   r24,(U_sPsTEST_ss_AAA)
   lds   r25,(U_sPsTEST_ss_AAA+1)
   cp   r22,r24
   cpc   r23,r25
   cpc   r20,r1
   cpc   r21,r1
 


Das ist zwar nett gemeint und verhindert sicher, dass man Überraschungen durch Variablenüberläufe erlebt, aber es macht den Code extrem ineffizient auf dem Controller, wenn
- jedesmal die doppelte Anzahl Befehle abgearbeitet wird
- die entsprechenden Register natürlich auch freigemacht werden müssen
- vor allem anstatt der effizienten mul-Befehle eine wenig effiziente und zeitraubende Software-Multiplikation aufgerufen wird

Warum dieser Rückschritt in der Embedded AVR Compilerentwicklung? Und wird das wieder besser? Ist das ein Fall für einen Bugreport? So ist eine effiziente Programmierung nicht möglich.

Ich verwende für Embedded AVR den aktuellen Trunk. Und Optimierung steht auf -O3, aber auch auf -O4 wird das nicht besser.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von af0815 »

Kansst du schauen, ab wann das begonnen hat ? Einen Bugreport ist das sicher Wert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von Timm Thaler »

Unterschiedlich, ich hab ein Projekt vom April gefunden, da waren uint16-Vergleiche und Subtraktion schon auf 32bit aufgebläht, Multiplikation von uint16 lief aber noch mit nativen mul, Multiplikation von int16 mit uint8 lief schon mit fpc_mul_longint auf 32bit.

Anscheinend hat man versucht das zu vereinheitlichen, und dabei die bequemste, aber auch ressourcenfressendste Variante genommen.

Ich kann doch nicht sämtliche Multiplikationen und Vergleiche mit eigenen Funktionen abdecken, da kann ich ja gleich Assembler programmieren und brauch keine Hochsprache. Oder nehm halt C - was mir überhaupt nicht zusagt.

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von Hitman »

Also ich würde ebenfalls zu einem Bug Report raten. Du hast das ja nun schon etwas analysiert. Wenn du tiefer gehen willst, kannst du mit git bisect ja noch graben, wann das angefangen hat. So oder so hilft ein Bug Report aber, auf das Problem aufmerksam zu machen. Ich denke nicht, dass nur du das so siehst. Das wird sicherlich auch nicht im Sinne des Maintainers dieses Compiler Targets sein. Wahrscheinlich ist es ihm noch gar nicht aufgefallen (oder aber es ist - weil trunk - ein erwarteter, temporärer Nebeneffekt irgendeines Umbaus, der durchaus noch nicht final angesehen wird. Das kann man dir dann aber im Rahmen des Tickets beantworten :-))

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von af0815 »

Timm, kannst du ein absolutes komplettes Minimalbeispiel für die Fälle machen ? Ich habe immer den aktuell Fixes und den aktuellen Trunk, notfalls auch unter Ubuntu hier und teste das gerne gegen. Auch weitere sinnvolle fpc varianten wären für Tests möglich (an Platz mangelt es mir nicht, maximal an Zeit :-) ).

Damit könnte man auch besser argumentieren im Bugreport bzw. das ganze auch auf der Mailingliste für den fpc diskutieren.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von Timm Thaler »

Die Enumeration muss angeblich so:

https://bugs.freepascal.org/view.php?id=35873
https://www.freepascal.org/docs-html/current/prog/progsu59.html

Ich bin mir aber ziemlich sicher, dass das mal anders war - oder ich hab immer im Delphi-Mode compiliert.

Das wäre dann die Lösung: Delphi Mode oder per $PACKENUM erzwingen. Gefällt nicht.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von Timm Thaler »

Die Sache mit dem Compare

https://bugs.freepascal.org/view.php?id=35872

liegt anscheinend wirklich daran, dass eine Konstante automatisch Shortint ist. Und Unsigned + Signed wird immer zum größeren Signed. Also uint16 + int8 wird zu int32.

Da muss man erstmal drauf kommen. :shock: Denn int16 + int8 bleibt int16. Obwohl das natürlich genauso überlaufen kann wie ein uint16 + int8...

Die Lösung ist anscheinend: Für Variablen möglichst int verwenden, uint nur für Zähler, die man nicht vergleichen möchte. Auch wenn die Variablen nie negativ werden.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Embedded AVR erzeugt seit Neuestem ineffizienten Code

Beitrag von Timm Thaler »

Ich hab das jetzt mal für verschiedene Kombinationen durchprobiert: Der Compiler entscheidet je nach Kombination entsprechend https://www.freepascal.org/docs-html/ref/refsu4.html, welcher Datentyp rauskommt. Dabei werden Konstanten immer als signed geführt, will man die mit einem unsigned verwenden ohne zu wechseln muss man die Konstanten auf unsigned casten.

Das ist natürlich nervig, weil es auch mehr Code erzeugt, aber war wohl eine Designentscheidung für Pascal, die man nun so hinnehmen muss.
Dateianhänge
AVR_integer.png

Antworten