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

Reply via email to