[Top][All Lists]
[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 themwith Windows Live Hotmail.
http://imagine-windowslive.com/hotmail/?locale=en-us&ocid=TXT_TAGHM_migration_HM_mini_protection_0507