Cse 322 Programming Languages and Compilers Lecture 11

  • Slides: 35
Download presentation
Cse 322, Programming Languages and Compilers Lecture #11, May 10, 2007 • More optimizations

Cse 322, Programming Languages and Compilers Lecture #11, May 10, 2007 • More optimizations (local, loop, global) • Liveness Analysis, • Spilling, • Problems with Jumps, • Ranges, • Intervals, • Linear Scan register allocation. 9/21/2021 1

Cse 322, Programming Languages and Compilers More Optimizations • Local Optimizations – – –

Cse 322, Programming Languages and Compilers More Optimizations • Local Optimizations – – – Constant Folding Constant Propagation Copy Propagation Reduction in Strength In Lining Common sub-expression elimination • Loop Optimizations – Loop Invariant s – Reduction in strength due to induction variables – Loop unrolling • Global Optimizations – Dead Code elimination – Code motion » Reordering » code hoisting 9/21/2021 2

Cse 322, Programming Languages and Compilers Constant Folding • Subexpressions whose operands are all

Cse 322, Programming Languages and Compilers Constant Folding • Subexpressions whose operands are all constants can be carried out at compile-time. • E. g. X : = 2 * 4 Rather than generating Movi 2 r 5 Movi 4 r 7 Prim "*" [r 5, r 7] r 9 . . . Generate this instead Movi 8 r 9 . . . • Code like this is not ordinarily written by programmers but is often the result of translation of index calculations. 9/21/2021 3

Cse 322, Programming Languages and Compilers Constant Propagation • Sometimes we know a symbolic

Cse 322, Programming Languages and Compilers Constant Propagation • Sometimes we know a symbolic value is a constant. So we can propagate the constant and generate better code: 1 2 3 4 step : = 4 total : = 0 i : = 1 total : = x [i + step] • Note that because there are no possible paths to 4 that do not pass through 1, 2 and 3 we know that i+step can be computed by (1+4) which is known at compile time to be 5. 9/21/2021 4

Cse 322, Programming Languages and Compilers Copy Propagation • Assignments of one variable to

Cse 322, Programming Languages and Compilers Copy Propagation • Assignments of one variable to another also propagate information: x: =y. . . total : = Z[x] • Note if my translation knows that y is stored in some register, R 7, I can use R 7 rather than fetching x from memory • Copy propagation my remove all references to x completely. This allow makes the assignment to x dead code and a candidate to further optimization. 9/21/2021 5

Cse 322, Programming Languages and Compilers Reduction in Strength • Some sequences of code

Cse 322, Programming Languages and Compilers Reduction in Strength • Some sequences of code can be replaced with simpler (or less expensive) sequences. x : = 2 * y could be replaced by x : = y + y • Exponentiation by 2 by multiply – x ^2 == x * x • Multiplication by factor of 2 by shift 9/21/2021 6

Cse 322, Programming Languages and Compilers In - Lining • Some calls to functions

Cse 322, Programming Languages and Compilers In - Lining • Some calls to functions (especially primitives like +, -, *, absolute value, ord and char) can be inlined as a sequence of machine instructions instead of a call to a library routine. i : = abs(j) Bneg j L 2 Mov j i Br L 3 L 2: Neg j R 2 Mov R 2 i L 3: 9/21/2021 7

Cse 322, Programming Languages and Compilers Common Sub-expressions • Common subexpressions can be exploited

Cse 322, Programming Languages and Compilers Common Sub-expressions • Common subexpressions can be exploited by not duplicating code x : = z[j+2] - w[j+2] T 1 : = j+2 x : = z[T 1] - w[T 1] • Note that common subexpressions often occur even when they are not in the user level code. – E. g. Subscript computations on two multi-dimensional arrays with the same dimensions will often have common sub expressions even if the index to the arrays are completely different 9/21/2021 8

Cse 322, Programming Languages and Compilers Loop Invariants • Computations inside loops which remain

Cse 322, Programming Languages and Compilers Loop Invariants • Computations inside loops which remain invariant each time around the loop can be computed once outside the loop rather than each time around the loop. For i : = 1 to N do { total : = x[i] / sqr(n) + total } T 1 : = sqr(n) For i : = 1 to N do { total : = x[i] / T 1 + total } • Note that index calculation may also introduces computations which are invariant around the loop. 9/21/2021 9

Cse 322, Programming Languages and Compilers Induction Variables and reduction in strength • Variables

Cse 322, Programming Languages and Compilers Induction Variables and reduction in strength • Variables which vary in a regular way around loops are called induction variables. • For loop variables are obvious cases, but implicit induction variables give much opportunity for optimization. For i : = 1 to 10 do { k : = i * 4; total : = x[i] + w[k] } • Note that k varies as a linear function of i. i : = 1 k : = 4 while i <= 10 do { total : = x[i] + w[k] i : = i + 1; k : = k + 4 } 9/21/2021 10

Cse 322, Programming Languages and Compilers Induction Variables (cont. 1) i : = 1

Cse 322, Programming Languages and Compilers Induction Variables (cont. 1) i : = 1 k : = 4 while i <= 10 do { total : = x[i] + w[k] i : = i + 1; k : = k + 4 } • Note that x[i] and w[k] are computed by formulas like: r 4 : = add(x) + lowbound(x) + i; load r 4 • Note that add(x) + lowbound(x) can be moved outside the loop and this introduces another induction variable xptr : = add(x) + lowbound(x) i : = 1 k : = 4 while i <= 10 do { total : = (xptr + i)* + w[k] i : = i + 1; k : = k + 1} 9/21/2021 11

Cse 322, Programming Languages and Compilers Induction Variables (cont. 2) xptr : = addr(x)

Cse 322, Programming Languages and Compilers Induction Variables (cont. 2) xptr : = addr(x) + wptr : = addr(w) + i : = 1 k : = 4 while i <= 10 do { total : = (xptr i : = i + 1; k lowbound(x) lowbound(w) + i)* + (wptr + k)* : = k + 4 } xptr : = addr(x) + lowbound(x) +1 wptr : = addr(w) + lowbound(w) + 4 bound = xptr + 10 while xptr <= bound do { total : = xptr* + wptr* xptr : = xptr + 1; wptr : = wptr + 4 } 9/21/2021 12

Cse 322, Programming Languages and Compilers Loop Unrolling • Loop with low trip count

Cse 322, Programming Languages and Compilers Loop Unrolling • Loop with low trip count can be unrolled. This does away with the loop initialization and test for termination conditions. list : = [1, 2] while (list <> nil) do { total : = total + hd(list); list : = tail(list) } total : = total + hd(list) list : = tl(list) total : = total + hd(list) 9/21/2021 13

Cse 322, Programming Languages and Compilers Dead Code Elimination • Automatic generation techniques often

Cse 322, Programming Languages and Compilers Dead Code Elimination • Automatic generation techniques often generate code that is unreachable. debug : = false; if debug then print x; f(x); • Because of constant propagation it is possible to tell at compile-time that then branch will never be executed. 9/21/2021 14

Cse 322, Programming Languages and Compilers Code Motion (reordering) • Sometimes reordering statements that

Cse 322, Programming Languages and Compilers Code Motion (reordering) • Sometimes reordering statements that do not interfere, allows other more powerful optimizations to be come applicable. Push R 2 Movi 7 R 3 Pop R 4 Movi 7 R 3 Push R 2 Pop R 4 Movi 7 R 3 Mov R 2 R 4 • Now copy propagation might remove R 2 altogether 9/21/2021 15

Cse 322, Programming Languages and Compilers Code Motion (Code Hoisting) • Branches in code

Cse 322, Programming Languages and Compilers Code Motion (Code Hoisting) • Branches in code sometimes repeat identical calculations. • These calculations can sometimes be “hoisted” before the branch, then they don’t have to be repeated. • This saves space, but not time. if g(x) then else x : = (d*2) + w / k x : = (d*2) - w / j T 1 : = (d*2); if g(x) then x : = T + w / k else x : = T - w / j • Multi branch “case” statements can make this quite a space saver 9/21/2021 16

Cse 322, Programming Languages and Compilers Code Hoisting in Nested Lang’s Procedure P (a,

Cse 322, Programming Languages and Compilers Code Hoisting in Nested Lang’s Procedure P (a, b: int); var x : int = 5; function f(y: int): int; begin x : = a+b - 3; return x + y end; begin for i : = 1 to 3 do print f(i) end; • Note that x : = a+b - 3; could be hoisted out of the nested function, then hoisted out of the loop. Procedure P (a, b: int); var x : int = 5; function f(y: int): int; begin return x + y end; begin x : = a+b - 3; for i : = 1 to 3 do print f(i) end; 9/21/2021 17

Cse 322, Programming Languages and Compilers Register Allocation • Task: Manage scarce resources (registers)

Cse 322, Programming Languages and Compilers Register Allocation • Task: Manage scarce resources (registers) in environment with imperfect information (static program text) about dynamic program behavior. • General aim is to keep frequently-used values in registers as much as possible, to lower memory traffic. Can have a large effect on program performance. • Variety of approaches are possible, differing in sophistication and in scope of analysis used. 9/21/2021 18

Cse 322, Programming Languages and Compilers Spilling • Allocator may be unable to keep

Cse 322, Programming Languages and Compilers Spilling • Allocator may be unable to keep every ``live'' variable in registers; must then ``spill'' variables to memory. Spilling adds new instructions, which often affects the allocation analysis, requiring a new iteration. • If spilling is necessary, what should we spill? Some heuristics: – Don't spill variables used in inner loops. – Spill variables not used again for ``longest'' time. – Spill variables which haven't been updated since last read from memory. 9/21/2021 19

Cse 322, Programming Languages and Compilers Simplistic approach • Assume variables ``normally'' live in

Cse 322, Programming Languages and Compilers Simplistic approach • Assume variables ``normally'' live in memory. • Use existing (often redundant) fetches and stores present in IR 1. • So: only need to allocate registers to IR temporaries (T 5 etc. ). • Ignore possibility of spills. • Use simple linear scan register allocator based on liveness intervals. 9/21/2021 20

Cse 322, Programming Languages and Compilers Liveness • To determine how long to keep

Cse 322, Programming Languages and Compilers Liveness • To determine how long to keep a given variable (or temporary) in a register, need to know the range of instructions for which the variable is live. • A variable or temporary is live immediately following an instruction if its current value will be needed in the future (i. e. , it will be used again, and it won't be changed before that use). 9/21/2021 21

Cse 322, Programming Languages and Compilers Example | T 2 : = 3 |

Cse 322, Programming Languages and Compilers Example | T 2 : = 3 | T 3 : = T 2 | T 4 : = T 3 + 4 | T 4 : = T 2 + T 4 | a : = T 4 | live after instruction: T 2 T 3 T 2 T 4 (nothing) • It's easy to calculate liveness for a consecutive series of instructions without branches, just by working backwards. 9/21/2021 22

Cse 322, Programming Languages and Compilers First, compute vars of an IR exp fun

Cse 322, Programming Languages and Compilers First, compute vars of an IR exp fun vars. Of x = case x of BINOP(m, x, y) => vars. Of x @ vars. Of y | RELOP(m, x, y) => vars. Of x @ vars. Of y | CALL(f, xs) => vars. Of. F vars. Of xs | MEM x => vars. Of x | NAME s => [] | TEMP n => [TEMP n] | PARAM n => [PARAM n] | MEMBER(x, n) => vars. Of x | VAR n => [VAR n] | CONST (s, ty) => [] | STRING s => [] | ESEQ(ss, x) => vars. Of. F vars. Of. St ss @ vars. Of x 9/21/2021 23

Cse 322, Programming Languages and Compilers Next, compute vars of an IR stmt and

Cse 322, Programming Languages and Compilers Next, compute vars of an IR stmt and vars. Of. St stmt = case stmt of MOVE(x, y) => vars. Of x @ vars. Of y | JUMP n => [] | CJUMP(m, x, y, n) => vars. Of x @ vars. Of y | LABEL n => [] | CALLST(f, xs) => vars. Of. F vars. Of xs | RETURN x => vars. Of x | STMTlist ss => vars. Of. F vars. Of. St ss | COMMENT(s, message) => vars. Of. St s and vars. Of. F f [] = [] | vars. Of. F f (x: : xs) = f x @ vars. Of. F f xs 9/21/2021 24

Cse 322, Programming Languages and Compilers Helper functions • We treat lists as sets,

Cse 322, Programming Languages and Compilers Helper functions • We treat lists as sets, so we need functions that – Remove an element from a set – Unions two sets • Note there will only ever be one element with a given value in a set. fun remove x [] = [] | remove x (y: : ys) = if x=y then ys else y : : remove x ys; fun union [] ys = ys | union (x: : xs) ys = if List. exists (fn z => z=x) ys then union xs ys else x : : (union xs ys) 9/21/2021 25

Cse 322, Programming Languages and Compilers Work backwards fun defines (s as MOVE(target, src))

Cse 322, Programming Languages and Compilers Work backwards fun defines (s as MOVE(target, src)) live = union (vars. Of src) (remove target live) | defines s live = union (vars. Of. St s) live fun ann. Live (s: : ss) live ans = ann. Live ss (defines s live) ((s, live): : ans) | ann. Live [] live ans = ans; fun live stmts = ann. Live (rev stmts) [] [] 9/21/2021 26

Cse 322, Programming Languages and Compilers Jumps cause problems L 1: T 1 :

Cse 322, Programming Languages and Compilers Jumps cause problems L 1: T 1 : = 0 T 2 : = T 1 + 1 T 3 : = T 3 + T 2 T 1 : = (2 * T 2) if T 1 < 1000 GOTO L 1 return T 3 | | | T 1 T 3 T 2 T 3 T 1 T 3 • Consider the above IR program. It is labelled by the results obtained from the previous algorithm. • But, what happens if we jump back to L 1, the 2 nd to last statement should still state that T 1 is live, because it could still be used in the dynamic flow of the program. 9/21/2021 27

Cse 322, Programming Languages and Compilers Correct Liveness 1. 2. L 1: 3. 4.

Cse 322, Programming Languages and Compilers Correct Liveness 1. 2. L 1: 3. 4. 5. 6. • T 1 : = 0 T 2 : = T 1 + 1 T 3 : = T 3 + T 2 T 1 : = (2 * T 2) if T 1 < 1000 GOTO L 1 return T 3 | | | T 1 T 3 T 2 T 3 T 1 T 3 A live range is a set of pairs. Each pair indicates a range where the variable is live. – T 1 (1, 1) (4, 5) – T 2 (2, 3) – T 3 (1, 5) 9/21/2021 28

Cse 322, Programming Languages and Compilers Computing Ranges • The result of computing the

Cse 322, Programming Languages and Compilers Computing Ranges • The result of computing the liveness is a list of variables for each line number. Eg. 1. [[TEMP 1, 2. , [TEMP 1, 3. , [ 4. , [ 5. , [TEMP 1, 6. , [ 7. , []] • TEMP 2, TEMP TEMP 3] 3] 3, ] 3] 3] 3] We look for contiguous variables in consecutive line numbers for each variable. 9/21/2021 29

Cse 322, Programming Languages and Compilers Computing ranges • Given such a list, we

Cse 322, Programming Languages and Compilers Computing ranges • Given such a list, we comput the range for a single variable (i. e. Temp 1) by making a pass over the list. • We repeat for each variable. 1. [[TEMP 2. , [TEMP 3. , [TEMP 4. , [TEMP 5. , [TEMP 6. , [TEMP 7. , []] 9/21/2021 1, TEMP 3, TEMP 2, TEMP 1, TEMP 3] 3] 3] 2] 3] 3] Range for Temp 1 [(5, 5), (1, 2)] Range for Temp 2 [(3, 4)] Range for Temp 3 [(1, 6)] 30

Cse 322, Programming Languages and Compilers ML code The idea is to carry a

Cse 322, Programming Languages and Compilers ML code The idea is to carry a option type indicating if we are in an active run for variable name. If we are in an active run, and we find a line that doesn’t have the variable, end the run. If we’re not in a run, and we find the variable, start a new run. fun range name [] line NONE ans = ans | range name [] line (SOME(x, y)) ans = (x, y): : ans | range name (rs: : rss) line interval ans = (case (List. find (fn x => x=name) rs, interval) of (NONE, NONE) => range name rss (line+1) NONE ans | (NONE, SOME(x, y)) => range name rss (line+1) NONE ((x, y): : ans) | (SOME _, NONE) => range name rss (line+1) (SOME(line, line)) ans | (SOME _, SOME(x, y)) => range name rss (line+1) (SOME(x, line)) ans) 9/21/2021 31

Cse 322, Programming Languages and Compilers From Ranges to intervals • Computing intervals from

Cse 322, Programming Languages and Compilers From Ranges to intervals • Computing intervals from ranges is easy. • Find the smallest start line number, and the largest finish line number in a set of ranges. – [(5, 5), (1, 2)] -> (1, 5) fun max [x] = x | max (x: : xs) = let val n = max xs in if x < n then n else x end; fun min [x] = x | min (x: : xs) = let val n = min xs in if x < n then x else n end; fun interval ranges = let fun fst (x, y) = x fun snd (x, y) = y in (map fst ranges) , max (map snd ranges)) end; 9/21/2021 32

Cse 322, Programming Languages and Compilers Live ranges and register allocation – T 1

Cse 322, Programming Languages and Compilers Live ranges and register allocation – T 1 (1, 1) (4, 5) – T 2 (2, 3) – T 3 (1, 5) • Two variables with no overlapping ranges can share the same register. Note that T 1 and T 2 could be stored in the same physical register. • APPROXIMATION TECHNIQUE • Compute live intervals, which are the first and last statement that a variable can be live. Coalesce the ranges. – T 1 (1, 5) – T 2 (2, 3) – T 3 (1, 5) 9/21/2021 33

Cse 322, Programming Languages and Compilers Linear Scan Register Allocation 1. Compute startpoint and

Cse 322, Programming Languages and Compilers Linear Scan Register Allocation 1. Compute startpoint and endpoint of the live interval for each temporary (Temp i). Store the intervals in a list in order of increasing start point. Range for [(TEMP Temp 1 [(5, 5), (1, 2)] Temp 2 [(3, 4)] Temp 3 [(1, 6)] 1, 1, 5), (TEMP 3, 1, 6), (TEMP interval (1, 5) interval (3, 4) interval (1, 6) 2, 3, 4)] 2. Initialize set active : = [ ] and pool of free registers = all usable registers. 3. For each live interval i in order of increasing start point: 1. For each interval j in active, in order of increasing end point 1. if endpoint[j] >= startpoint[i] break to step 3. 2 2. Remove j from active 3. Add register[j] to pool of free registers. 2. Set register[i] : = NEXT FREE REGISTER, AND REMOVE IT from pool. If pool is already empty. need to spill. 3. Add i to active, sorted by increasing end point. 9/21/2021 34

Cse 322, Programming Languages and Compilers Fixing problems with Jumps 1. 2. L 1:

Cse 322, Programming Languages and Compilers Fixing problems with Jumps 1. 2. L 1: 3. 4. 5. 6. • • • T 1 : = 0 T 2 : = T 1 + 1 T 3 : = T 2 + T 3 T 1 : = (2 * T 1) if T 1 < 1000 GOTO L 1 return T 3 | | T 2 T 1 | T 1 T 3 T 3 T 3 To fix problems with jumps we break code into basic blocks. We use simple analysis within blocks (where the flow of control is simple) And more complex analysis between blocks. 9/21/2021 35