Expression related optimizations: Constant Folding, Constant Propagation, Global Propagation, Strength Reduction, Common Subexpression Elimination, Partial Redundancy Elimination, Induction Variable Elimination, Reassociation
Loop related optimizations: Loop Invariant Code Motion, Loop Peeling, Loop Unrolling, Loop Distribution, Loop Autoparallelization, Loop Fusion, Loop Fission, Loop Interchange, Loop Tiling/Stripmining, Vectorization, Scalarization
Memory/cache related optimizations: Cache blocking, False Sharing Elimination, Structure Peeling, Structure Splitting, Array Contraction, Multi-dimensional Array Dimension Reordering
Control flow related optimizations: Code block re-ordering (by frequency), Branch prediction (by static analysis/feedback guided), Code hoisting/sinking (to optimize CPU pipeline), Automatic Inlining, Tail Call Optimization
Code generation related optimizations: Register allocation (np complete), Peephole optimization, Superoptimization (no one really does this yet, but cool nonetheless)
Analysis (interprocedural/intraprocedural): Alias Analysis (flow/context (in)sensitive), Points-to Analysis, Escape Analysis, du chain Analysis, Live Variables Analysis, Memory Access Pattern Analysis (to guide memory layout optimizations), Available Expressions/Copies Analysis, Loop Dependency Analysis, Control Flow Analysis, Dominator data flow Analysis, Globals Analysis
Miscellaneous: Static Single Assignment, Data Flow Analysis (in, out, transfer, meet!), Worklist Algorithm (for Data Flow Analysis!), Symbolic Execution/Abstract Interpretation
Writing straightforward code is the best thing you can do for a compiler. They can tell exactly what you want to do, and do their best to generate the fastest/most memory efficient code possible. Help compiler help you!
Also, compiler usually comes with several different levels of optimizations. And you can tune each one of these optimizations, like you would with a racing car. Read the manual!