AVR-GCC Bug? if (uint16_t-Typ == 0).

OP #877244
Lesenswert?

Hallo,

ich habe ein Problem mit dem AVR-gcc und seiner Optimierung. Angenommen 
sei folgender Ausschnitt aus einem C-Code:
1
    volatile static uint16_t readBytes;
2

3
    if ( (readBytes) == 0 )
4
    {
5
        PORTD = 0x01; // Beispiel
6
    }

Ohne irgendeine Optmierung (-Ox weggelassen) erzeugt gcc diesen Code:
1
lds  r24, 0x0060
2
lds  r25, 0x0061
3
sbiw  r24, 0x00  
4
breq  .+2        
5
rjmp  .+244
der für mich auch ok aussieht. Mit Optimierung (-O, -O2, -Os) erzeugt er 
das hier:
1
lds  r24, 0x0060
2
lds  r25, 0x0061
3
or  r24, r25
4
brne  .+4
Ich denke dass dieser Code falsch ist - in den Registern r24 und r25 
befinden sich das High- und Low-Byte der uint16 Variable. Eine 
Oder-Operation ergibt für mich als Test auf Null keinen Sinn (im 
Gegensatz zum unoptimierten Fall s.o.).

Diese Änderung ergibt sich erst, wenn ein O-Parameter angegeben wird. 
Wenn ich versuche, die Optimierungen mit -fxxx Parametern nachzubauen, 
bekomme ich das Problem nicht, allerdings ändert sich die Code-Größe 
auch nicht.

Das ganze ist natürlich in ein größeres Projekt eingebettet, so dass ich 
Optimierung haben will, schon aus Geschwindigkeitsgründen. Allerdings 
habe ich noch einen (diffusen) Fehler in der Software, die von der 
Optimierungsstufe abhängig ist, und diesen suche ich nun.

Die Frage ist nun, habe ich bei obigem Beispiel irgendwo einen 
Denkfehler? Warum "funktioniert" die Optimierung nur, wenn ich einen 
O-Parameter angebe, und nicht mit den f-Parametern? Auch über Literatur 
zu dem Thema und Tipps aus der Praxis wäre ich dankbar.

Vielen Dank schon mal für die Hilfe,
Michael

PS: Eingesetzte Version: avr-gcc 4.2.2 aus der Ubuntu 8.04 Standard 
Installation, avr-libc 1.4.7-1 (auch aus Ubuntu). Binutils 2.18-3. Eine 
eigene Toolchain zu erstellen wollte ich eigentlich vermeiden, aber wäre 
wohl einer der nächsten Schritte falls ich keine bessere Idee habe...
#877247
Lesenswert?

Michael S. wrote:

> Eine Oder-Operation ergibt für mich als Test auf Null keinen Sinn

Für mich schon. Der Code ist völlig korrekt. Das Ergebnis dieser 
Operation ist genau und nur dann 0 wenn beide Register 0 sind, und das Z 
Flag gibt diesen Sachverhalt wieder.
#877254
Lesenswert?

Worauf in diesem Zusammenhang allerdings zu achten ist: Wenn readBytes 
den Wert 0x0100 hat und im Interrupt auf 0x00FF runtergezählt wird, dann 
kann es vorkommen, dass der Test das untere Byte vor und das obere Byte 
nach dem Interrupt läd und damit fälschlicherweise auf 0 erkennt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren