Lesson 5 of 7
Optimization
Optimizers rewrite a program in many small steps that keep its behavior the same but make it faster. You'll see the common passes and what they mean for how you write code.
What -O2 does to your code (each pass, repeatedly):
constant folding 3 * 60 -> 180
constant propagation x=5; y=x+1 -> y=6
dead code removal if(false){...} -> (gone)
common subexpression (a*b) + (a*b) -> t=a*b; t+t
function inlining call sq(x) -> x*x (no call)
loop invariant hoist for(...){k=n*4} -> k=n*4; for(...)
strength reduction i * 2 -> i << 1
loop unrolling 4 iterations -> straight-line code
vectorization sum loop -> SIMD: 8 adds/instr
Passes enable each other: inlining exposes constants,
folding kills branches, killing branches exposes more.
That's why they run in a loop until nothing changes.// Try on godbolt.org — gcc -O2:
int sum_to(int n) {
int total = 0;
for (int i = 1; i <= n; i++)
total += i;
return total;
}
// The compiler recognizes the pattern and emits the
// CLOSED FORM — no loop at all:
// n * (n + 1) / 2 (a few instructions, O(1))
// And this function:
int always_42(void) {
int x = 6, y = 7;
return x * y;
}
// compiles to:
// mov eax, 42
// retThe contract is the 'as-if' rule: the optimizer may do anything as long as observable behavior is unchanged. This is also where behavior matters most — in C, signed overflow is UB, so the assumes it never happens and deletes your 'if (x + 1 < x)' overflow check as dead code. The optimizer is simply applying the language's rules.
Finished reading?Mark it done to track your progress.
Tip: use the ← and → keys to move between lessons.