avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [avr-gcc-list] GCC does useless 16-bit operations


From: Dave Hansen
Subject: RE: [avr-gcc-list] GCC does useless 16-bit operations
Date: Fri, 11 May 2007 10:07:46 -0400

From: address@hidden


For the C code:

uint8_t tx_producer_index;
...
{
  ...
  uint8_t temp = (tx_producer_index + 1) % 64;

Note that the literals 1 and 64 have type int, so tx_producer_index is promoted to int before the addition, and the % must be performed on signed operands.


I get the assembly from gcc 3.4.4:

[... 8 instructions...]

>From gcc 4.1.2, it's even worse:

[... 8 instructions plus a function call ...]

The C code:

  uint8_t temp = (tx_producer_index + 1U) % 64;

Note this time, that 1U has type unsigned, so tx_producer_index is promoted to unsigned before the addition, and 64 is promoted to unsigned before the % operation takes place.


is much much better with 3.4.4:

[... 4 instructions ...]

But

  uint8_t temp = (tx_producer_index + (uint8_t) 1) % 64;

is the same as without the cast. So two issues:

It would be. The + operator has two unsigned char operands, so they both must be promoted (to signed int) before the addition. The cast ultimately has no effect where it is. You should get better results if you changed the cast to (uint16_t) or (unsigned). But that's just what 1U does anyway.


1) Shouldn't the type of "(uint8_t) 1" be strictly no larger than the type
   of 1U?

No larger, yes. But (uint8_t)1 has to be promoted to (int)1 before any operation other than assignment can take place on it. So it gains a sign bit.


2) gcc 4.1.2 generates unuseably bad code for int16_t % int8_t when the
   int8_t is a positive power-of-2 constant.

Well, IMHO it's unusable only if it generates an incorrect result. Consider what happens if the int16_t is negative.


3) I'm not totally sure, but I think it shouldn't need 16-bit math in any
   of this. And gcc 4.1.2 does use 16-bit math for the addition with the
   64 unchanged, but doesn't if the 64 is replaced with 64U, which must
   be an error of some sort.

Not really. Remember that with 64U, the sum has to be promoted to unsigned before the % operation. GCC can apparently prove to itself that 8 vs. 16-bit math won't change the result in that case.

As long as the code generates the correct results, it is at most a missed optimization. Which is worth fixing, don't get me wrong. I'm just trying to determine why the results are what they are, and the most sensible way to work around them.

Regards,

  -=Dave

_________________________________________________________________
Catch suspicious messages before you open them—with Windows Live Hotmail. http://imagine-windowslive.com/hotmail/?locale=en-us&ocid=TXT_TAGHM_migration_HM_mini_protection_0507





reply via email to

[Prev in Thread] Current Thread [Next in Thread]