In some cases, we could unroll loops to speed up the code execution. This is especially effective for short loops. After a loop is unrolled, there are no loop indices to be tested and fewer branches are executed each round in the loop.
The table below shows the effect of unrolling loops.
Loops | Unrolling loops | |
---|---|---|
C source code |
#include <avr/io.h> int main(void) { uint8_t loop_cnt = 10; do { PORTB ^= 0x01; } while (--loop_cnt); } |
#include <avr/io.h> int main(void) { PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; PORTB ^= 0x01; } |
AVR Memory Usage |
Program: 94 bytes (1.5% Full) (.text + .data + .bootloader) Data: 0 bytes (0.1% Full) (.data + .bss + .noinit) |
Program: 142 bytes (1.7% Full) (.text + .data + .bootloader) Data: 0 bytes (0.0% Full) (.data + .bss + .noinit) |
Cycle counter | 80 | 50 |
Compiler optimization level | -O2 | -O2 |
By unrolling the "do { } while ( )" loop, we significantly speed up the code execution from 80 clock cycles to 50 clock cycles.
Be aware that the code size is increased from 94 bytes to 142 bytes after unrolling the loop. This is also an example to show the tradeoff between speed and size optimization.