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
          }
  }

Reply via email to