Reported by geckosenator on avrfreaks.net
Code: int sat; static volatile long data[3]; static volatile int datacount[3]; static volatile int chan; static volatile long val; int __attribute__((always_inline)) transfer(int data) { return (*(int *)((0x00))); } int init_status; long read_scale(void) { long val; if(init_status) val |= (long)transfer(0) << 16; val |= (long)transfer(0) << 8; return val; } void get_mode(int *mode, int *psw) { int val = transfer(0); *psw = val & 0x10 ? 1 : 0; } long __attribute__((always_inline)) read_data(void) { long val; val <<= 8; if(init_status) val |= transfer(0); return val - 0x80; } void function1() { long data2 = read_data(); sat = (data2 > 1) || (data2 < -100); val += data2; data[chan] += val; datacount[chan] ++; } void function2(long *data) { int i, j; data[i] += i + j; } Compile with: Code: avr-gcc -std=gnu99 -fgnu89-inline -Os -mmcu=at90usb1287 -c testcase.c -o testcase.S -S Then look in testcase.S for: Code: .L16: ldi r16,lo8(-128) mov r14,r16 ldi r16,hi8(-128) mov r15,r16 ldi r16,hlo8(-128) mov r16,r16 <----- bad, this does nothing! ldi r16,hhi8(-128) <-- nice, we just clobbered r16 mov r17,r16 add r14,r18 adc r15,r19 adc r16,r20 adc r17,r21 sts (sat)+1,__zero_reg__ It looks like the compiler got confused and tried to use r16 in two different ways at the same time. The bug occurs in peephole optmisation. Here avr-gcc looks for a spare register R16-R31 that it can use to load a constant value into operands which are located in lower register (R2-R15). The test for "spare" occurred before instruction. So if the instruction happened to use that register (because it was spare), bad things happen.Typically this will happen with long - or long long registers. -- Summary: [AVR] avr-gcc generating incorrect assembly for expression with the long constant operands Product: gcc Version: 4.2.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: aesok at gcc dot gnu dot org GCC target triplet: avr-*-* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37466