Where We Are

Source code (character stream) if (b == 0) a = b; Lexical Analysis Syntax Analysis Errors Semantic Analysis IR Generation Optimizations Correct program In High IR IR Lowering Program In Low IR

1 2

What Next? Optimizations

• At this point we could generate assembly code Source code (character stream) from the low-level IR if (b == 0) a = b; Lexical Analysis Syntax Analysis Errors • Better: Semantic Analysis – Optimize the program first IR Generation – Then generate code Correct program Optimize In High IR • If optimization performed at the IR level, then IR Lowering they apply to all target machines Program In Low IR Optimize

3 4

1 What are Optimizations? Why Optimize?

• Optimizations = code transformations that • Programmers don’t always write optimal code – improve the program can recognize ways to improve code (e.g., avoid recomputing same expression)

• Different kinds • High-level language may make some – space optimizations: improve (reduce) memory use oppptimizations inconvenient or impossible to express – time optimizations: improve (reduce) execution time a[ i ][ j ] = a[ i ][ j ] + 1; • Code transformations must be safe! • High-level unoptimized code may be more – They must preserve the meaning of the program readable: cleaner, modular int square(x) { return x*x; }

5 6

Where to Optimize? Many Possible Optimizations • Usual goal: improve time performance • Many ways to optimize a program • Problem: many optimizations trade off space • Some of the most common optimizations: versus time Function Inlining Function Cloning • Example: – Increases code spp,pace, speeds up one loop Constant propagation – Frequently executed code with long loops: Loop-invariant code motion space/time tradeoff is generally a win Common sub-expression elimination – Infrequently executed code: may want to optimize code space at expense of time Branch prediction/optimization Loop unrolling • Want to optimize program hot spots

7 8

2 Constant Propagation Constant Folding • If value of variable is known to be a constant, replace • Evaluate an expression if operands are known use of variable with constant at (i.e., they are constants) •Example: •Example: n = 10 x = 1.1 * 2; ⇒ x = 2.2; = 2 for (i=0; i

9 10

Algebraic Simplification Copy Propagation

• More general form of constant folding: take • After assignment x = y, replace uses of x with y advantage of usual simplification rules • Replace until x is assigned again a * 1 ⇒ a a* 0 ⇒ 0 a / 1 ⇒ a a + 0 ⇒ a x = y; x = y; b || false ⇒ b b && true ⇒ b if (x > 1) ⇒ if (y > 1) s = x * f(x - 1); s = y * f(y - 1); • Repeatedly apply the above rules (y*1+0)/1 ⇒ y*1+0 ⇒ y*1 ⇒ y • What if there was an assignment y = z before? – Transitively apply replacements • Must be careful with floating point!

11 12

3 Common Subexpression Elimination Elimination

• If program computes same expression multiple • Eliminate code that is never executed time, can reuse the computed value •Example: #define debug false •Example: s = 1; a = b+c; a = b+c; ⇒ s = 1; if (debug) cb+c;c = b+c; ⇒ ca;c = a; d = b+c; d = b+c; print(“state = ”, s); • Common subexpressions also occur in low-level code in address calculations for array accesses: • Unreachable code may not be obvious in low IR (or in high-level languages with unstructured a[i] = b[i] + 1; “goto” statements)

13 14

Unreachable Code Elimination Dead Code Elimination

• Unreachable code in while/if statements when: • If effect of a statement is never observed, – Loop condition is always false (loop never executed) eliminate the statement – Condition of an if statement is always true or always false (only one branch executed) x = y+1; y = 1; ⇒ y = 1; if (false) S ⇒ ; x=2x = 2z;*z; x = 2*z; if (true) S else S’ ⇒ S • Variable is dead if value is never used after if (false) S else S’ ⇒ S’ definition while (false) S ⇒ ; • Eliminate assignments to dead variables while (2>3) S ⇒ ; • Other optimizations may create dead code

15 16

4 Loop Optimizations Loop-Invariant Code Motion • If result of a statement or expression does not • Program hot spots are usually loops change during loop, and it has no externally- (exceptions: OS kernels, ) visible side-effect (!), can hoist its computation • Most execution time in most programs is out of the loop spent in loops: 90/10 is typical • Often useful for array element addressing • Loop optimizations are important , effective , computations – invariant code not visible at and numerous source level • Requires analysis to identify loop-invariant expressions

17 18

Code Motion Example Another Example

• Identify invariant expression: • Can also hoist statements out of loops • Assume x not updated in the loop body: for(i=0; i

19 20

5 Strength Reduction Strength Reduction • Replaces expensive operations (multiplies, divides) by cheap ones (adds, subtracts) • Can apply strength reduction to • Strength reduction more effective in loops computation other than induction variables: • = loop variable whose value is depends linearly on the iteration number x * 2 ⇒ x + x • AlApply strength hd reducti on to i idinduction vari iblables i*2i * 2c ⇒ i << c s = 0; s = 0; v = -4; i / 2c ⇒ i >> c for (i = 0; i < n; i++) { for (i = 0; i < n; i++) { v = 4*i; ⇒ v = v+4; s = s + v; s = s + v; } }

21 22

Induction Variable Elimination Loop Unrolling

• If there are multiple induction variables in a loop, can • Execute loop body multiple times at each eliminate the ones that are used only in the test iteration condition • Need to rewrite test using the other induction variables •Example: • Usually applied after strength reduction for (i = 0; i< n; i++) { S }

s = 0; v=-4; s = 0; v = -4; • Unroll loop four times: for (i = 0; i < n; i++) { for (; v < (4*n-4);) { for (i = 0; i < n-3; i+=4) { S; S; S; S; } v = v+4; ⇒ v = v+4; for ( ; i < n; i++) S; s = s + v; s = s + v; } } • Gets rid of ¾ of conditional branches! • Space-time tradeoff: program size increases

23 24

6 Function Inlining Function Cloning

• Replace a function call with the body of the function: • Create specialized versions of functions that are called from different call sites with different arguments int g(int x) { return f(x)-1; } int f(int n) { int b=1; while (n--) { b = 2*b }; return b; } void f(int x[], int n, int m) { for(int i=0; i

25 26

When to Apply Optimizations Summary • Many useful optimizations that can transform Function inlining code to make it faster High IR Function cloning Constant folding Constant propagation • Whole is greater than sum of parts: Dead code elimination oppppgtimizations should be applied together, Loop-iitdtiinvariant code motion LIRLow IR Common sub-expression elimination sometimes more than once, at different levels Strength reduction Constant folding & propagation Branch prediction/optimization • Problem: when are optimizations are safe? Loop unrolling Assembly Cache optimization

27 28

7