3 ms·
I kept a short list of the times I was disappointed by avr-gcc on my last project (11.1.0 mind you, not the ancient 5.4.0 one maintained by Microchip): Get hig
by maltaisn 4y ago
I kept a short list of the times I was disappointed by avr-gcc on my last project (11.1.0 mind you, not the ancient 5.4.0 one maintained by Microchip):
Get highest bits with a right shift: https://godbolt.org/z/nqseMvMh5 https://godbolt.org/z/nqseMvMh5
- Expected: shift only highest byte of word (3 cycles).
- Actual: all bytes of word are shifted several times (184 cycles, +18B).
Copy low nibble to high nibble in bit field struct: https://godbolt.org/z/x8nrTWPja https://godbolt.org/z/x8nrTWPja
- Expected: swap & or byte (4 cycles).
- Actual: mul used to shift left (7 cycles, +6B).
Extract bits 6:11 from an byte array encoding a 16 bit field: https://godbolt.org/z/EPTnbjGeP https://godbolt.org/z/EPTnbjGeP
- Expected: build result into high byte by shifting bits 6:7 from low byte into high byte using rotate (11 cycles).
- Actual: mul used to shift (16 cycles, +8B), or build result into low byte (13 cycles, +4B).
Unrolled memcpy: https://godbolt.org/z/Yvbr7vT5a https://godbolt.org/z/Yvbr7vT5a
- Expected: memcpy uses `ld X+` followed by `st Z+`. The same is expected here (20 cycles)
- Actual: the compiler doesn't know about that the X register support post increment, creating `adiw`/`sbiw` chains instead (29 cycles, +18B). This is especially bad when the compiler is register starved when writing structs, it makes the program a lot larger than it should be. It's very easy to get a register starve situation: read from a pointer (register Z) to write a struct referred to by a pointer (X register), with both pointers originally stored on the stack (Y register). Oops, the struct uses the X register, every access generates 2x the code it should.