Many compiler optimizations focus on loops. If you look at the literature, you'll see the vast majority of papers are 'I made a loop of $this form go faster'. Why is that?
Loops, by their nature, are blocks of code that are executed multiple times, possibly many millions of times. Thus any improvement to that code pays off a million times over. The general approach with loop optimizations is to move code from inside the loop to outside the loop — then it's only executed once. Two classic examples are Load Hoisting and Store Sinking. Loop optimizations can get quite complicated, and the semantics of the source language can make certain optimizations easier (or harder).
- Loop Rotation A simple(st?) optimization applied to
- Load Hoisting Moving loads to before a loop.
- Store Sinking Moving stores to after a loop.
- Induction Variable Elimination Reducing iteration bookkeeping.
- Loop Unrolling Performing multiple logical iterations per physical iteration.
- Loop Collapsing Merging nested loops into a single loop.
- Loop Merging Merging adjacent loops into a single loop.
- Loop Unswitching Moving conditional statements out of a loop.
- Loop Reversal Inverting the direction of iteration.
- Vectorization A whole other set of optimizations.