80 likes | 197 Views
This article explores essential strategies for optimizing register allocation, minimizing unnecessary operations, and reducing costly operations in programming. It highlights the importance of efficient use of registers in architectures, common subexpression elimination, dead code elimination, and jump optimization. Techniques such as reduction in strength, constant folding, and function call optimizations are discussed in detail, including the benefits of inlining and eliminating tail recursion. This comprehensive guide is aimed at improving code performance and efficiency.
E N D
Optimization CPSC 388 Ellen Walker Hiram College
Areas for Optimization • Register allocation • Unnecessary operations • Costly operations
Register Allocation • In most architectures, values must be in registers to be operated on • In memory: load, act, store • Must allocate values (temporary and variable) to a limited # of registers • If both memory & register operations are available, registers are faster
Unnecessary Operations • Common subexpression elimination • Save partial values instead of recomputing them • E.g. t = (a*a / (a*a + b*b)) • Dead code elimination • Don’t generate unreachable code • Jump optimization • Avoid jumping to jump statements • Useless code • Store X ; Load X
Costly Operations : Reduction in Strength • Don’t call a power function if you can multiply • (x*x vs x^2) • Don’t multiply when you can shift • (x<<4 vs. 16*x)
Costly Operations: Constant Folding • Don’t generate operations on constants; do them at compile time • Circ = 2 * PI * r • If a variable will act like a constant for part or all of a program, transform its expressions also (constant propagation)
Costly Operations: Function Calls • Function calls have overhead • Create a new activation frame • Set up parameters & return value • Remove activation frame & jump to return • Avoid by inlining (insert function code directly • Eliminate tail recursion with loop
Recognizing Tail Recursion • Last step of recursive program is the recursive call • No use of local variables after the recursive call • Trace looks like “>” (all the way in, then all the way out)