This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug rtl-optimization/34791] [avr] optimisation of 8-bit logic sometimes fails
- From: "david at westcontrol dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 16 Feb 2010 10:46:04 -0000
- Subject: [Bug rtl-optimization/34791] [avr] optimisation of 8-bit logic sometimes fails
- References: <bug-34791-15632@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Comment #1 from david at westcontrol dot com 2010-02-16 10:46 -------
There are many other cases where 8-bit optimisation is missing - C's integer
promotion gets in the way. This is particularly common when dealing with a
compile-time constant - there is no way in C to say that "0x3f" is 8-bit rather
than a 16-bit int.
Another example of code with this problem is:
void foo(void) {
static unsigned char count;
if (++count & 0x3f) {
PORTC &= ~0x01;
} else {
PORTC |= 0x01;
}
}
Both the "&" and the comparison with zero are done as 16-bit.
One work-around is to use this macro:
#define const_byte(x) ({ static const __attribute__((__progmem__)) \
unsigned char v = x; v; })
Then we can write:
#define const_byte(x) ({ static const __attribute__((__progmem__)) \
unsigned char v = x; v; })
uint8_t bar3(uint8_t x, uint8_t y) {
return data[y ^ (x & const_byte(0x0f))];
}
147 bar3:
148 /* prologue: function */
149 /* frame size = 0 */
150 008c 8F70 andi r24,lo8(15) ; tmp45,
151 008e 8627 eor r24,r22 ; tmp45, y
152 0090 E0E0 ldi r30,lo8(data) ; tmp48,
153 0092 F0E0 ldi r31,hi8(data) ; tmp48,
154 0094 E80F add r30,r24 ; tmp48, tmp45
155 0096 F11D adc r31,__zero_reg__ ; tmp48
156 0098 8081 ld r24,Z ; , data
157 /* epilogue start */
158 009a 0895 ret
160
As far as I can see, this generated code is optimal.
The macro works because it forces the value to be 8-bit, rather than a 16-bit
compile-time constant. However, the compiler is still smart enough to see that
since it's a "const" with known value, it's value can be used directly. As a
side effect, the static "variable" must be created somewhere - by using
__progmen__, we create it in flash rather than wasting ram. Even that waste
could be spared by garbage-collection linking, or by using a dedicated segment
rather than .progmem.data.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34791