------- 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