http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51447
Matthijs Kooijman <matthijs at stdin dot nl> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |matthijs at stdin dot nl --- Comment #19 from Matthijs Kooijman <matthijs at stdin dot nl> --- In case anyone else comes across here and wonders: This fix made it into 4.8, but was not backported into 4.7.3. Regarding the bug description that says "4.7 regression", I have also observed this bug on avr-gcc 4.3.3, so it's not a regression introduced in 4.7. I also noticed this bug on the AVR platform, using 4.7.2. Just in case it helps (perhaps for others to find this bug when Googling for avr-gcc), here's the testcase and bugreport I was preparing before I found this one. // // Under some circumstances, writes to a global register variable are // optimized away, even though that changes behaviour. The below example // illustrates this. // // When compiled as-is, the writes to the variable "global" are removed. // However, when compiling with -DDO_CALL, which adds a function call to // the main function, the writes are preserved. This leads me to believe // that the optimizer sees that main() isn't calling any functions, so // it must be safe to just remove the writes (even though documentation // [1] says "Stores into this register are never deleted even if they // appear to be dead, but references may be deleted or moved or // simplified.") // // It seems that a second condition (in addition to no functions called) // is that the main function does not return. If we add a return path, // the writes show up again. // // However, removing these writes does not seem sane, since there is // also an interrupt routine, which can access the variable, but the // optimizer is apparently not aware that this is a possibility. // // // Tested using: // avr-gcc -mmcu=attiny13 register.c -S -o - -O // avr-gcc -mmcu=attiny13 register.c -S -o - -O -DDO_CALL // avr-gcc -mmcu=attiny13 register.c -S -o - -O -DDO_RETURN // // [1]: // http://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html#Global-Reg-Vars #include "avr/io.h" #include "avr/cpufunc.h" // Define a global variable in a register register char global asm("r16"); // Just a dummy function void foo() { // Add some nops so this function doesn't get inlined _NOP(); _NOP(); _NOP(); } // Define an ISR that accesses the global. This doesn't actually seem to // make a different, except that if this wasn't here, removing writes to // the global would be acceptable void ISR(INT0_vect) { PORTB = global; } void main() { global = 1; while(1) { #ifdef DO_CALL foo(); #endif #ifdef DO_RETURN return; #endif } }