mal wieder ein Beispiel - da derartiges oft vorkommt:
...
uint32_t result = 0;
uint8_t result8 = 0;
int main(void) {
result = (uint32_t)a * b;
result8 = result >> 18;
return 0;
}
wird in -Os -O2 -O3 so übersetzt :
ldi r18,18 ; ,
1: lsr r25 ; D.1928
ror r24 ; D.1928
ror r23 ; D.1928
ror r22 ; D.1928
dec r18 ;
brne 1b
sts result8,r22 ; result8, D.1928
bei ">> 16" macht er halbwegs korrekt einen einfachen "movw r22,r24"
(obwohl der auch überflüssig ist).
Es sollte doch naheliegend bei uint32_t >> 18 ein(kein) movw + 2 x 16bit
ror/lsr gemacht werden - einfach so:
lsr r25
ror r24
lsr r25
ror r24
sts result8,r24
ist das zuviel verlangt? das ist doch recht schlimm.
gibts AVR-Compiler die da deutlich besser sind?
nur mal wieder ein Beispiel für die die vielen arg unzulänglichen
Optimierungen. da braucht man doch eigentlich kein fortgeschrittene KI?
jetzt greif ich so unter die Arme:
int main(void) {
result = (uint32_t)a * b;
result8 = (uint16_t)(result >> 16) / 4;
return 0;
}
-- -O3 -------
movw r22,r24 ; tmp50, D.1928
clr r24 ; tmp50
clr r25 ; tmp50
lsr r23 ; tmp51
ror r22 ; tmp51
lsr r23 ; tmp51
ror r22 ; tmp51
sts result8,r22 ; result8, tmp51
.LM7:
ldi r24,lo8(0) ; <result>,
ldi r25,hi8(0) ; <result>,
=> na ja. aber warum löscht er stur r24,r25? und dann merkt er beim
return nicht mal das schon 0en drin sind ;-) ...
liegt das allgemein am GCC oder am AVR-Teil?
Die 32-Bit Shift-Operationen sind für AVRs nicht optimal implementiert.
Das ist bekannt und betrauert, aber bislang fand sich unter den
Trauergästen keiner, der es dann auch verbessern wollte.
GCC geht eher davon aus, dass Shift-Operationen billig sind. Das hat
manchmal negative Seiteneffekte in Form vom Fehloptimierungen, denn das
sind sie bei AVRs meistens nicht. Schrumpfmaschinchen wie AVRs sind kein
Hauptziel der GCC Entwicklung, da stehen eher dickere Boliden wie
x86/amd64 und ARM im Vordergrund.
kxr schrieb:> ist das zuviel verlangt? das ist doch recht schlimm.> nur mal wieder ein Beispiel für die die vielen arg unzulänglichen> Optimierungen. da braucht man doch eigentlich kein fortgeschrittene KI?
avr-gcc ist ein Open-Source Compiler, du kannst mithelfen ihn zu
verbessern.
Wenn solche Änderungen trivial für sich sind, mach eben ein Patch,
spiels ein und die Sache ist aus der Welt.
Kein Grund, um zu weinen.
Eine kurze Überschlagsrechnung für 32-Bit Shifts:
· Es gibt 3 mögliche Shifts (LSL, LSR, ASR)
· Es gibt 32 gültige Shift-Offsets (0..31)
· Es gibt Derivate mit MOVW und ohne
· Es gibt 4 Möglichkeiten, wie sich Quelle und Ziel überlappen können
· Es gibt mindestens 2 Optimierungs-Szenarien: Speed oder Codegröße
Macht 1536 = 3·32·2·4·2 Möglichkeiten.
Dabei sind noch nicht einmal Rotate oder variable Offsets
berücksichtigt.
Zu den Implementierungen gehören dann auch noch die
Kostenbeschreibungen.
Also, los geht's mit deiner KI!
Zudem gibt's noch mehr Unterscheidungskriterien:
· Wird eine Schleife ausgegeben und wird das Loop-Register danach
weiter verwendet oder nicht?
· Ist nach der Registerklasse zu unterscheiden?
· Soll der Shift auf Memory passieren oder in Registern?
Johann L. schrieb:> Es gibt mindestens 2 Optimierungs-Szenarien: Speed oder Codegröße> Macht 1536 = 3·32·2·4·2 Möglichkeiten.
Zur Vereinfachung könnte man ja zunächst mal ansetzen, daß der kürzeste
Code auf einem AVR in der Regel auch der schnellste ist, RISC sei Dank.
Das reduziert die Varianten schon mal auf die Hälfte.
Oliver
Oliver schrieb:> Zur Vereinfachung könnte man ja zunächst mal ansetzen, daß der kürzeste> Code auf einem AVR in der Regel auch der schnellste ist, RISC sei Dank.
No. Ein Librarycall für eine Division kostst:
2 Instruktionen zum Laden des Divisors
1 Instruktion für den Call
Am besten für -Os ist also eine Division :-)
Weiß man an der Stelle aber nicht. Und in ähnlich gelagerten Fällen auch
nicht. Bzw. die Lib ist eh drinne, aber über die Funktion weiß man eben
nix.
Zudem ist eine Schleife mitunter kürzer aber langsamer.
Wanzer schrieb:> Ansonsten gibt es ja> auch Compiler von Atmel.
So? Welchen denn?
Atmel baut ICs, Compiler bauen andere. ;-) Es gäbe den IAR, aber
das ist sowas wie der Mercedes unter den Compilern, da sind alle
Knöpfe dran vergoldet odre so.
Jörg Wunsch schrieb:> Atmel baut ICs, Compiler bauen andere. ;-) Es gäbe den IAR, aber> das ist sowas wie der Mercedes unter den Compilern, da sind alle> Knöpfe dran vergoldet odre so.
Hat jemand konkrete Erfahrungen wie der IAR bzgl. der hier diskutierten
und ähnlichen, sonstigen.. Sachen besser optimiert als der AVR GCC?
kxr schrieb:> Hat jemand konkrete Erfahrungen wie der IAR bzgl. der hier diskutierten> und ähnlichen, sonstigen.. Sachen besser optimiert als der AVR GCC?
Du kannst, je nach Programm, mit einigen Prozent bis vielleich maximal
so 20 % Codeeinsparung rechnen. Als Nachteil schlagen zu Buche, dass
du das Ganze nur noch auf einem Computer benutzen kannst, vor dem du
auch physisch davor sitzen musst (kein Terminalserver, keine virtuelle
Maschine — zumindest ist das der Stand, den ich noch davon kenne),
dass du einige Tausender dafür hinblättern musst, dass du mit jeder
neuen Version worst case wieder einige Stunden verbringen kannst, bis
der ganze Lizenz-Mift wieder in Sack und Tüten ist, und natürlich, dass
es ihn ausschließlich für ein Betriebssystem gibt.