Ho aperto un topic sui display a matrice di led alcuni giorni fa, ma vorrei generalizzare il problema. C'è qualcuno che si sia "scontrato" con le ottimizzazioni spinte per sfruttare la seppur poca potenza di calcolo degli AVR?
Da un paio di giorni sto cercando di capire se il seguente polinomio sia ottimizzabile:
addr = x + 64*(x>>5) + 16*(x>>4) + 64*(y>>3);
...soluzioni migliori non ne trovo in realtà, e così ho cercato di capire se fosse possibile ottimizzare riscrivendo il tutto in assembler inline...
__asm__ __volatile__ (
"mov __tmp_reg__, %2" "\n\t"
"ldi %0, 0x80" "\n\t"
"andi %2, 0x7" "\n\t"
"__shift_0:" "\n\t"
"asr %0" "\n\t"
"dec %2" "\n\t"
"brpl __shift_0" "\n\t"
"mov %2, __tmp_reg__" "\n\t"
"lsr %2" "\n\t"
"lsr %2" "\n\t"
"lsr %2" "\n\t"
"ldi %1, 0x40" "\n\t"
"mul %1, %2" "\n\t"
"movw %1,r0" "\n\t"
"add %A1, %3" "\n\t"
"adc %B1, 0" "\n\t"
"lsr %3" "\n\t"
"lsr %3" "\n\t"
"lsr %3" "\n\t"
"lsr %3" "\n\t"
"ldi r16, 0x10" "\n\t"
"mul r16, %3" "\n\t"
"add %A1, r0" "\n\t"
"adc %B1, r1" "\n\t"
"lsr %3" "\n\t"
: "=r" (bitval), "=r" (addr)
: "r" (y), "r" (x)
: "r0", "r1", "r16"
);
Il codice di cui sopra è incompleto, manca la parte riguardante il monomio 16*(x>>4) (mentre la parte iniziale riguarda un'altra operazione, cioè bitval = 128 >> (y&7)). Non l'ho continuato perché procedevo per passi ed eseguivo di volta in volta un benchmark... ottenendo gli stessi risultati che in C. A queste condizioni usare l'assembler è solo una perdita di tempo e complicazione inutile (può essere di esercizio, ammesso che tale esercizio abbia qualche scopo...).
La domanda è: è possibile ottimizzare dei monomi con forma n*(x>>s)? Purtroppo l'AVR ha istruzioni di shift logico o aritmetico che possono eseguire lo shift di un solo bit, quindi l'istruzione va ripetuta o reiterata...