Common Subexpression Elimination (CSE)
Redundancy | 8-minute read
- Replace repeated equivalent computations with a single computed value.
- Global Value Numbering (GVN) detects equivalences across blocks.
- Alias/memory dependence constrain load CSE; use alias analysis and MDSSA.
t1 = a*b; ...; t2 = a*b ⇒ t2 := t1 (if operands and flags identical, and no intervening defs)
Dead Code Elimination (DCE)
Liveness | 7-minute read
- Remove computations whose results are never used and have no side effects.
- Sparse DCE on SSA leverages use-def chains; aggressive DCE relies on side-effect analysis.
- Be careful with volatile/atomic operations and observable behavior.
if a then x=1 else x=2; return 0 ⇒ assignments to x are dead
Loop-Invariant Code Motion (LICM)
Loops | 9-minute read
- Hoist computations invariant within a loop to preheaders; sink post-invariant code.
- Requires dominance, alias checks, and safety (exceptions, traps).
- Combine with induction variable simplification and strength reduction.
for i in 0..n: y = a*b; z[i] = y + i ⇒ y = a*b; for i: z[i] = y + i
Inlining
Call overhead | 9-minute read
- Replace call sites with callee body; exposes more optimization but grows code size.
- Heuristics: callee size, hotness (PGO), devirtualization opportunities, recursion limits.
- Inline cost must consider register pressure and I-cache misses.
inline small hot getters; avoid inlining large cold functions
Pass interactions and ordering
Pipelines | 7-minute read
- Run passes in loops: inline → CSE/DCE/GVN → LICM → loop unroll/vectorize → cleanup.
- Preserve analyses or rebuild as needed; be aware of invalidation costs.
- IR-specific pipelines (LLVM new pass manager, etc.).
Cost models and heuristics
Heuristics | 7-minute read
- Static models approximate cycles/memory; dynamic (PGO) uses profiles.
- Model target ISA costs (latency/throughput), cache behavior, and branch prediction.
- Guard against code-size explosions with thresholds.
Exercises
Hands-on | 8-minute read
- Implement local CSE on a basic block; extend to global via GVN.
- Implement sparse DCE on SSA and test against tricky side-effect cases.
- Implement LICM with alias checks and hoist/sink across loop nests.
Optimization is engineering: combine solid analyses with pragmatic heuristics tuned to your targets.