Strategy for optimisation problem

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd just like to canvas opinion about the best way of hunting down a problem...

I have a reasonably complex programme. It works fine with the GCC optimisation set to -O0 (no optimisation) but, if I switch any sort of optimisation on it doesn't work the same. So, in these circumstances how would you go about solving the problem?

(I could just programme the AVR with the -O0 code as there is enough space, but if I have to use the code in a smaller part or get this again I'd like to know how to deal with it...

I've tried debugging in the simulator and strange things happen in some of the routines - like a parameter that's passed into a routine and is initially set to 1 suddenly becomes 8 and there is no code in the routine to change it!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you declare your global variables, which are changed in an ISR, as volatile? I think there's an explanation in the AVRLibC manual (FAQ section) which is included with each distribution of WinAVR.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I have all the globals that are changed in an ISR declared as volatile.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What about cycle-dependant operations? The compiler may be re-using registers, breaking the (standard) 4 cycle limits on operations like changing the clock prescaler.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have any uninitialized variables? Other than the embedded world's own special gotcha's, when a program works differently with the optimizer on, it nearly always turns out to be unintialized variables. The optimizer is only too happy to hand you whatever garbage is left over in the register that it wants to use -- with the optimizer off it will typically load a zero from the variable's storage location on first use.

-dave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> like a parameter that's passed into a routine and is initially set
> to 1 suddenly becomes 8 and there is no code in the routine to
> change it!)

This is completely normal. The parameter is passed in a register, and
with optimizations enabled, when the compiler notices the original
parameter is no longer needed, it can re-allocate the register to
another variable, or as temp space during expression calculations. As
the debug information would still indicate there were a connection
between your register and the original parameter, you then get the
impression the parameter had changed when it was actually only no
longer used. "no longer used" can be hidden in subtle ways here. For
example, if you use base an expression on that parameter, the compiler
might calculate the actual expression earlier, and then re-use the
parameter's register to store the intermediate result.

If you can at least nail the problem down to a particular part of your
code, it might be worth analyzing the generated assembly (or the
disassembly listing).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dbc wrote:
Do you have any uninitialized variables? Other than the embedded world's own special gotcha's, when a program works differently with the optimizer on, it nearly always turns out to be unintialized variables. The optimizer is only too happy to hand you whatever garbage is left over in the register that it wants to use -- with the optimizer off it will typically load a zero from the variable's storage location on first use.

-dave

Thanks, I'll check, but I'm pretty sure that I've not got any.

(The strange change in value was actually a call parameter and the routine it happens in doesn't modify it at all, it just uses it as an index into a table. So, as you can imagine, the new value is not entirely welcome.

Also, if I remove the function I just added (which is in a different source file - and I've checked all 15 lines of that over and over) that makes a call to the routine it goes back to working fine again when other code calls it, even with optimisation).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> ...doesn't modify it at all, it just uses it as an index into a table.

E. g. if your table elements are 8 bytes in size each, it would make
sense for the compiler to turn the index into a byte offset close to
the beginning of the function, but it might then keep it in the same
register as the parameter has once been passed in. The original
value (1) is apparently no longer used inside the function then, so
from the optimizer's point of view, that register is free for being
reallocated for the new purpose.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.