Too much optimisation

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

I've gone to a lot of effort with my latest project to ensure that it compiles under GCC and IAR. I was interested in the code size that each compiler generated. I had GCC set to -Os and IAR -z3 which I increased to -z6 (IAR size optimization). That's when the IAR code stopped working. I had the following code:

while(true)
{
    DISABLE_INTERRUPTS();
    if (Event To Process)
    {
        Process The Event;
    }
    ENABLE_INTERRUPTS();
}

The IAR compiler optimised it to:
sei
cli
if statement test
rjump to sei

Seems that if you have an sei and then a cli just after it, interrupts are never enabled. The working GCC code was:
cli
if statement test
sei
rjmp to cli

The rjmp between the sei and cli was enough to allow interrupts to be enabled.

A very subtle bug to be aware of when cranking up the optimisation on a compiler!

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

Well, gcc does have a habit of deleting code it feels that is useles.

if you have a wait like
for(a=0;a!=666;a++);

then gcc finds it useles. either turn the optimalizations off, or do
for(a=0;a!=666;a++)wdt_reset();

There are pointy haired bald people.
Time flies when you have a bad prescaler selected.

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

Quote:

Well, gcc does have a habit of deleting code it feels that is useles.

As does most compilers. And it is a good habit, IMHO. If you don't want any optimization you can turn it off.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"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] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Declare the loop variable as volatile and it won't optimise it out.

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

It all depends on 'Event To Process'. If that is testing some named variable you did not declare as 'volatile', then that is your problem. The compiler will compute the result once and reuse it if you do not modify the variable in your loop.

Most good C compilers will do this to some extent. I wonder if gcc decided on its own that it was not in your best interest to do that (obvious from the code).

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

Ummm--the situation as reported by vulcan doesn't include losing the test or the block. Rather, it has to do with the re-arrangement of the SEI-CLI pair. It seems that if they are back-to-back then no interrupt can get a word in edgwise. The datasheet bears this out, with a notation that CLI takes effect immediately, but with SEI

Quote:
When using the SEI instruction to enable interrupts, the instruction following SEI will be executed before any pending interrupts,...

so the IAR optimizer in its infinite wisdom has created a perhaps optimal code sequence but one with undesireable side effects on an AVR.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Hey Kiwi,
What outcomes did you get from your comparison of IAR versus GCC? I'm particually interested in code size, we have a Mega128 that's run out using WinAVR.

Cheers, :)

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

Seems most people read a post, see the word optimisation and simple assume that the problem has something to do with declaring a variable as volitile rather than reading the post properly.

In reply to the question in the previous post, after bumping the IAR compiler back to -z3 to get the code working and with GCC set to -Os, the GCC code is currently 6% smaller. Not too bad for a free compiler!
GCC 3.4
IAR 4.20

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

Quote:
Quote:
When using the SEI instruction to enable interrupts, the instruction following SEI will be executed before any pending interrupts,...

so the IAR optimizer in its infinite wisdom has created a perhaps optimal code sequence but one with undesireable side effects on an AVR.

With the explanation from the AVR specification, you should possibly always insert a _NOP() after _SEI() to be on the safe side. In an 'ideal' loop

while
{
   _CLI();
   _SEI();
}

it is clear that there has to be some sort of a jump somewhere, but you should perhaps not rely on the fact that the compiler inserts it at the 'correct' location.

Jörg.

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

I've placed a NOP at the end of the loop after the SEI and cranked the IAR optimization back up to -z6.

I've tried two different resource configs with my application. IAR beats GCC by 6% with one config and 8% with the other. I still think that GCC is pretty impressive for a free tool. My guess with larger applications you would probably see a 10% saving on code space using IAR, but then you should given it's price and knowledge of the architecture.

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

Depending on the structure of your program, you may expect to shave a percent or two off that differential if you switch to GCC 4.1.

EW has made a "pre release" of WinAVR which includes the new version of GCC. My largest ATmega128 application, with -Os optimization, shrinks from around 120 KB to around 116 KB when I switch between GCC 3.4.6 and GCC 4.1.1.

However, there have also been reports of some situations where the code may grow somewhat with the newer compiler...

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

> so the IAR optimizer in its infinite wisdom has created a perhaps
> optimal code sequence but one with undesireable side effects on an
> AVR.

I would be surprised to see *any* compiler knowing about this specific
peculiarity. I think any compiler optimizing well enough (so it even
*can* move the end of the loop to the top at all) is potentially prone
to fall into that trap.

> I still think that GCC is pretty impressive for a free tool.

GCC is known to be a very good compiler. In the i386 area, basically
only the Intel compiler can beat it, and only because it really
squeezes the last bit out of Intel's own CPUs (potentially causing
poorer code for CPUs like AMD64 then). The impressive thing is that a
target like the AVR, which is completely of minor importance to GCC,
which nobody in the GCC camp can test during their regression builds
(as there's currently no testsuite defined, as that would require a
script-based simulation backend), and which is something GCC has never
been designed for (GCC has been designed with 32-bit CPUs in mind)
still yields such a good optimization.

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

Quote:
..............and cranked the IAR optimization back up to -z6.

I do not use the command line, but isn't -z9 the highest optimization level? Ever tried that?

I always use maximum speed optimization (-s9 ?) in my projects as this leads to quite compact code, too.

On an ATmega88 '8k' project I found about the same size savings of the IAR compared to GCC that you also observed. The GCC 3.4 is good, the GCC 4.1 is even better, in many places it produces nearly the same code as the IAR (which looks near optimum for me). What it seems to lack in a direct comparison is recognition of 'same code' portions in the source code.

Jörg.