Disucussion: When is -O0 appropriate?

35 posts / 0 new
Last post
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

{whisper]I've half a hope he may have caught that point as well already

(in fact I don't think there'll be anyone who can think of ANY argument for not linking against libm.a by default - wonder if they'll include -std=gnu99 as well for all the "for(int i=0" folks?)

 

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

Just to clarify, here is an example of a small function that I checked by compiling with -O0 to make sure the function was operationally correct.

void T6963PutIconPixel(uint16_t x, uint16_t y, uint8_t colour)
{
  uint16_t offs = (x | y) ? (((y*240)+x) / 4) : 0;
  uint8_t msk = (x | y) ? (3<<((((y*240)+x)%4)<<1)) : (3<<0);
  uint8_t cmsk = (x | y) ? (colour<<((((y*240)+x)%4)<<1)) : (colour<<0);
  screen_overlay[offs] &= (uint8_t)~(msk);
  screen_overlay[offs] |= cmsk;
}

It took a few goes to get this correct.

Debugging with AVR Studio on -O0 code is much easier. Insight handles optimised code much better than AVR Studio actually, but it's easier to quickly check functionality of code under AVR Studio on windows.

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

An interesting example. When built into the following "program":

#include 

uint8_t screen_overlay[100];

void T6963PutIconPixel(uint16_t x, uint16_t y, uint8_t colour) 
{ 
  uint16_t offs = (x | y) ? (((y*240)+x) / 4) : 0; 
  uint8_t msk = (x | y) ? (3<<((((y*240)+x)%4)<<1)) : (3<<0); 
  uint8_t cmsk = (x | y) ? (colour<<((((y*240)+x)%4)<<1)) : (colour<<0); 
  screen_overlay[offs] &= (uint8_t)~(msk); 
  screen_overlay[offs] |= cmsk; 
}

int main(void) {
	T6963PutIconPixel(38, 56, 17);
	while(1);
}

then the -O0 version builds to 528 bytes on a mega168 and the -Os version to 272 bytes, almost half the size.

Quod erat demonstrandum.

 

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

This has nothing to do with running on a target, so who cares what size it ends up being with -O0?

Like I've said, debugging and verifying code in AVR Studio is much easier when gcc is set to -O0. This code was never run on a target when compiled with -O0.

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

BrianS wrote:
This has nothing to do with running on a target, so who cares what size it ends up being with -O0?

Like I've said, debugging and verifying code in AVR Studio is much easier when gcc is set to -O0. This code was never run on a target when compiled with -O0.

True.

But there exists sample code that can be taken directly out of an AVR datasheet, for example:

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
   /* Wait for completion of previous write */
   while(EECR & (1<<EEWE))
   ;
   /* Set up address and data registers */
   EEAR = uiAddress;
   EEDR = ucData;
   /* Write logical one to EEMWE */
   EECR |= (1<<EEMWE);
   /* Start eeprom write by setting EEWE */
   EECR |= (1<<EEWE);
}

which, when compiled under -o0 optimization, results in totally incorrect behaviour. No amount of source-level debugging is going to give you insight into why that operation is going wrong. However, using another debugging tool - observation of the interleaved assembly and source - will reveal the source of the problem.

As far as I'm concerned, the seemingly random jumping around phenomenon of stepping through optimized code isn't really a problem as long as the user is told to expect that this will be going on.

What really needs to be resolved, is the ability of the debugger to identify the correct locations of local variables which have been bound to registers. Right now, AVR Studio's insistence on looking at the SRAM for all variables, and its inability to cope with a single location being recycled for use with multiple different local variables at different points within the scope of the same function are the severe limitations preventing effective debugging with optimization enabled IMHO.

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

Totally agree with Luke's last paragraph. That is what seems to be the "problem" with optimised code.

A very "simplistic" fix would be for the ELF to contain a single bit flag to say "this was built with optimisation" and the debugger then simply to refuse to watch variables in this case ;)

Cliff

 

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

Yes, the problem with AVR Studio is its poor implementation of watching local vars.

I haven't looked at AVR Studio's V2 simulator, does it do any better?

The C examples in 99% of the AVR documentation are for the IAR compiler though. As usual with compilers, your mileage may vary. When debugging something like that, which has specific timing requirements, it's easy enough to check the cycle counter in the simulator or switch to the disassembly view to see what's going on.

Each debugging session has its own set of requirements.

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

As others have noted,
debugging can be much easier compiling with -O0.
-O0 can also cause problems, e.g. with 4 cycle limits.
Perhaps newbies should be required
to make an explicit choice.
Make the default something like -Oyou_must_choose .

Is there a clean (usable by a newbie)
way to tell AVR-Studio to use different
-O flags on different files?
Even if -O0 would otherwise be useful, one might
want to make sure the result will fit in memory.

Is it racist to discriminate against someone who changes species?

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

Quote:

Is there a clean (usable by a newbie)
way to tell AVR-Studio to use different
-O flags on different files?

Yes. Under Project, Configuration Options. Select Custom Options. Then mark the file, and add the compiler option you want (in this case "-O0").

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington]

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

clawson wrote:
{whisper]I've half a hope he may have caught that point as well already

(in fact I don't think there'll be anyone who can think of ANY argument for not linking against libm.a by default - wonder if they'll include -std=gnu99 as well for all the "for(int i=0" folks?)

Yes, I already knew about those. IIRC, -std=gnu99 will be in the 4.13 SP1 release. We did take a look at automatically linking in libc and libm. However, that will take a bit more work to do then we had time for. We would like to target that for 4.13 SP2.

Pages