Gast
#3826970
Der Vergleich zweier Nibbles (siehe unten) wird vom GCC-Compiler auf 16 Bit aufgeblasen. Ist dies von C-Standard so vorgesehen? Wie kann man das auf 8 Bit reduzieren?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
|
Anzeige
|
C: "unsigned char"-Vergleich immer mit 16 Bit?
Gast
#3826970
Der Vergleich zweier Nibbles (siehe unten) wird vom GCC-Compiler auf 16 Bit aufgeblasen. Ist dies von C-Standard so vorgesehen? Wie kann man das auf 8 Bit reduzieren?
Gast
#3826976
Die beiden Konstanten 0x0F und 4 sind vom Typ int und damit 16 Bit. Der Compiler macht alles rivhtig. Optimizer einschalten. Compi schrieb: > Die beiden Konstanten 0x0F und 4 sind vom Typ int und damit 16 Bit. Der > Compiler macht alles rivhtig. Tut er, aber nicht wirklich deshalb. Sondern weil er sowieso wie vorgeschrieben in "int" rechnet. Es geht aber nicht darum, ob er es richtig macht, sondern ob er gut macht. Und er kann erkennen, dass beide Operationen ohne Veränderung des Wertes auch in 8 Bits gerechnet werden dürfen. Und das tut er in Version 4.7.2 mit eingeschalteter Optimierung auch: lds r24,x mov r25,r24 swap r25 andi r25,lo8(15) andi r24,lo8(15) cpse r25,r24
Gast
#3826988
D. h. auch mit einem 'cast' (siehe unten) komme ich nicht weiter? Was kann ich stattdessen machen?
Gast
#3827001
A. K. schrieb: > Optimizer einschalten. Nutzt nichts. Keine der Stufen 1, 2 ,3 und S verändern das Ergebnis. Im Gegenteil der Code wird insgesamt länger. WinAVR Studio 4 4.18 Die Version von Atmels Studio ist irrelevant. Die Version vom Compiler ist wichtig, also vom gcc in WinAVR. Wie schon gezeigt: avr-gcc 4.7.2 macht es besser.
Gast
#3827017
Tja, da habe ich die Version 4.3.3 Tja, dann probier mal ein aktuelles Studio. Also das nicht unbedingt allseits geliebte Monster, in dem Atmel den Compiler mitliefert. Der ist m.W. neuer.
Gast
#3827033
A. K. schrieb: > Tja, dann probier mal ein aktuelles Studio. Also das nicht unbedingt > allseits geliebte Monster, in dem Atmel den Compiler mitliefert. Der ist > m.W. neuer. Diesen Vorschlag habe ich befürchtet :) Wieso gleich das "Monster", http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx sollte es doch auch tun. Der Vollständigkeit halber Das hier
bringt dir überhaupt nichts. Noch nicht mal theoretisch. Zum einen ist das Ergebnis der & Verknüpfung formal immer noch ein int. Zum anderen ist der Datentyp auf der rechten Seite eines >> vollkommen irrelevent. Wenn schon, dann musst du dafür sorgen, das beim Vergleich ein unsigned char mit einem unsigned char verglichen wird
ob der Compiler jetzt die Absicht dahinter erkennt oder nicht, hab ich nicht ausprobiert. Kannst du ja machen.
Gast
#3827171
Führt nicht zum Erfolg. Liegen die Zwischenergebnisse in Variablen, dann ist der Zielcode kürzer.
Gast
#3827578
Karl Heinz schrieb: > (unsigned char) (checksum & 0x0F) | _______________________________| Das ist auch ein int. Wenn schon unsigned char) (checksum & (unsigned char) 0x0F) oder? schrieb: > Das ist auch ein int. Wenn schon > unsigned char) (checksum & (unsigned char) 0x0F) Was jedoch absolut nichts dran ändert, dass dies de jure als "int" gerechnet werden muss. So ist C nun einmal definiert. Nur kann ein Compiler clever genug sein, um festzustellen, ob das überhaupt nötig ist. Und daran ändern die Casts nichts. Sehr wohl aber die Version des Compilers. Es ist vollkommen korrekt und notwendig daß der compiler bei dem hier: if ((checksum & 0x0F) == (checksum >> 4)) einen 16 bit vergleich durchführt. Da gibts nichts wegzuoptimieren, Du willst explizit wissen ob auf der rechten Seite nach dem Shift **alle** verbleibenden 12 bits identisch sind mit dem was auf der linken Seite rauskommt. Du willst explizit 12 Bits verglichen haben, wie soll er das mit nur einem Byte hinbekommen? Der Compiler setzt das genauso um wie Du es angefordert hast. Da steht nirgendwo was daß er nur das low-byte betrachten soll. Wenn Dich nur das low-Byte von checksum interessisrt dann caste checksum vorher nach uint8_t und mach **damit** Deinen Vergleich. Also zum Beispiel so: if (((uint8_t)checksum & 0x0F) == ((uint8_t)checksum >> 4)) Bernd K. schrieb: > Da gibts nichts wegzuoptimieren, Doch, weil aus der ursprüngliche Frage ersichtlich ist, dass "checksum" uint8_t sein muss. Weshalb deine Casts absolut nichts bringen. A. K. schrieb: > Bernd K. schrieb: >> Da gibts nichts wegzuoptimieren, > > Doch, weil aus der ursprüngliche Frage ersichtlich ist, dass "checksum" > uint8_t sein muss. Weshalb deine Casts absolut nichts bringen. Ich bin mir nicht sicher daß das aus der Frage ersichtlich ist. Wenn checksum uint8_t ist dann führt er den Vergleich nur mit 8 bit durch wie gewünscht und sinnvoll. Zumindest gcc macht das (avr-gcc so wie er momentan von Atmel vertrieben wird und wahrscheinlich auch ältere oder neuere oder anderweitig andere Versionen). Bernd K. schrieb: > Ich bin mir nicht sicher daß das aus der Frage ersichtlich ist. Ich schon. Es ist nämlich nur ein einziger Load-Befehl im Code. > Wenn checksum uint8_t ist dann führt er den Vergleich nur mit 8 bit > durch wie gewünscht und sinnvoll. Zumindest gcc macht das (avr-gcc so > wie er momentan von Atmel vertrieben wird und wahrscheinlich auch ältere > oder neuere oder anderweitig andere Versionen). So weit waren wir gestern auch schon. Nur hat er eben einen steinalten GCC 4.3.3 im Einsatz. Der scheint sich anders zu verhalten als neuere Versionen. ich muss mich korrigieren. Da scheint wirklich was dran zu sein:
uint16_t checksum = P_DATA_0;
if ((checksum & 0x0F) == ((uint8_t)checksum >> 4)) {
P_DATA_1 = 42;
}
vs
uint8_t checksum = P_DATA_0;
if ((checksum & 0x0F) == ((uint8_t)checksum >> 4)) {
P_DATA_1 = 42;
}
ersteres hab ich zuerst getestet, daher mein vorheriges Posting, das
erzeugt 8 bit code, letzteres jedoch nicht nicht, egal was und wo ich
caste. Das muss ein Bug im Compiler sein.
Bernd K. schrieb: > Das muss ein Bug im Compiler sein. Fehlende Optimierung ist normalerweise nur dann wirklich ein Bug, wenn es in einer Vorversion schon mal besser war. Ansonsten ist das eher als Wunsch der Anwender zu sehen. A. K. schrieb: > Bernd K. schrieb: >> Das muss ein Bug im Compiler sein. > > Fehlende Optimierung ist normalerweise nur dann wirklich ein Bug, wenn > es in einer Vorversion schon mal besser war. Siehe mein obiges Beispiel: uint16_t checksum = P_DATA_0; if ((checksum & 0x0F) == ((uint8_t)checksum >> 4)) { P_DATA_1 = 42; } 20e: 80 91 0c 01 lds r24, 0x010C 212: 98 2f mov r25, r24 214: 9f 70 andi r25, 0x0F ; 15 216: 82 95 swap r24 218: 8f 70 andi r24, 0x0F ; 15 21a: 98 13 cpse r25, r24 21c: 03 c0 rjmp .+6 ; 0x224 <main+0x1e> 21e: 8a e2 ldi r24, 0x2A ; 42 220: 80 93 0d 01 sts 0x010D, r24 vs: uint8_t checksum = P_DATA_0; if ((checksum & 0x0F) == ((uint8_t)checksum >> 4)) { P_DATA_1 = 42; } 20e: 80 91 0c 01 lds r24, 0x010C 212: 28 2f mov r18, r24 214: 2f 70 andi r18, 0x0F ; 15 216: 30 e0 ldi r19, 0x00 ; 0 218: 82 95 swap r24 21a: 8f 70 andi r24, 0x0F ; 15 21c: 90 e0 ldi r25, 0x00 ; 0 21e: 28 17 cp r18, r24 220: 39 07 cpc r19, r25 222: 19 f4 brne .+6 ; 0x22a <main+0x24> 224: 8a e2 ldi r24, 0x2A ; 42 226: 80 93 0d 01 sts 0x010D, r24 also scheint er schon optimieren zu können wenn er den expliziten cast sieht, also ist dieser optimierungscode irgendwo vorhanden, jedoch im zweiten Beispiel scheint er zuerst den (nun unnötigen) cast wegzuoptimieren und danach vergisst er wieder daß er es nur mit 8 bit zu tun hat. Also ist die Optimierung prinzipiell vorhanden und offensichtlich auch so gewollt, wird aber unter gewissen Umständen nicht angewendet. Also ganz klar ein Bug. Weinstein schrieb: > A. K. schrieb: >> Tja, dann probier mal ein aktuelles Studio. Also das nicht unbedingt >> allseits geliebte Monster, in dem Atmel den Compiler mitliefert. Der ist >> m.W. neuer. > > Diesen Vorschlag habe ich befürchtet :) Es ist gar nicht so schwierig, in AVR Studio 4.18 einen aktuelleren Compiler zu aktivieren: 1. avr-gcc-4.7.2-mingw32.zip von der Seite http://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20%28Win32%29/ herunterladen 2. Die Zip-Datei direkt unter C:\ entpacken, so dass ein Verzeichnis C:\avr-gcc-4.7.2-mingw32 entsteht. 3. Umgebungsvariable PATH anpassen auf C:\avr-gcc-4.7.2-mingw32\bin (d.h. alten Pfad auf C:\Programme\WinAVR-20100110\bin überschreiben). 4. Verzeichnis utils aus dem alten Ver5zeichnis WinAVR-20100110 (i.a. unter C:\Programme) nach C:\avr-gcc-4.7.2-mingw32 kopieren 5. Umgebungsvariable PATH anpassen/erweitern auf C:\avr-gcc-4.7.2-mingw32\utils\bin (d.h. alten Pfad überschreiben) 6. Registry bearbeiten:
ändern auf: C:\avr-gcc-4.7.2-mingw32\WinAVR-20100110-uninstall.exe Dieses Uninstall-Programm existiert zwar gar nicht, aber AVR Studio hat die seltsame Eigenart, dass es den Pfad auf das Uninstall-Programm auswertet, um den AVR-gcc zu finden. Krank, aber funktioniert perfekt. AVR Studio 4.18 starten, ein Projekt laden und unter Project -> Configuration Options -> Custom Options kontrollieren, ob "Use WinAVR" auch angehakt ist und avr-gcc auf C:\avr-gcc-4.7.2-mingw32\bin\avr-gcc.exe make auf C:\avr-gcc-4.7.2-mingw32\utils\bin\make.exe _automatisch_(!) eingestellt wurde. 7. Compilieren und über das kleinere Binary freuen P.S. Sollte das avr-size-Programm nicht mehr funktionieren, kann man das aus dem alten WinAVR-20100110 Unterverzeichnis rüberkopieren. P.P.S Solltest Du einen anderen Pfad für avr-gcc-4.7.2-mingw32 verwenden, dann darauf achten, dass im kompletten Pfad kein Leerzeichen vorkommt. Also "C:\Program Files" ist suboptimal. P.P.P.S Ich selber habe mir eigene REG-Dateien zur Umschaltung gestrickt. So kann ich zwischen avr-gcc-4.3.3, 4.7.2, 4.8.1, 4.9.2 (pre) mit einem Doppelklick umschalten. Die Version 4.7.2 ist sehr stabil und kann ich nur jedem empfehlen. 4.8.1 hat kleine Macken (u.a. falsche Warnings bzgl. Interrupt-Vektoren). 4.9.2 ist noch keine endgültige, sondern eine Vorab-Version. Bernd K. schrieb: > Also ist die Optimierung prinzipiell vorhanden und offensichtlich auch > so gewollt, wird aber unter gewissen Umständen nicht angewendet. Also > ganz klar ein Bug. ... ein alter Hut und mindestens sein 2009 bekannt: http://gcc.gnu.org/PR41076 Immer offen für Lösungsvorschläge :-) Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|