Cse 322 Programming Languages and Compilers Lecture 11
- Slides: 35
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 – – – 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 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 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 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 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 (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 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 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 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 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) + 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 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 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 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 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, 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) 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 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 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 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 | 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 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 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, 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)) 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 : = 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. 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 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 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 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 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 (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 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: 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
- Cs 421 uiuc
- Cs 421 programming languages and compilers
- Cse 340 principles of programming languages
- Vineeth kashyap
- What is an interpreter
- Finding and understanding bugs in c compilers
- Symbol table implementation in lex and yacc
- Introduction to interpreter
- Real-time systems and programming languages
- Advantages of application software
- Real-time systems and programming languages
- Binarymove c++
- Cross compilers
- Compilers book
- Function of compiler
- Difference between front end and back end of compiler
- 01:640:244 lecture notes - lecture 15: plat, idah, farad
- Real time example of multithreading in java
- Programming languages levels
- Introduction to programming languages
- Plc coding language
- Joey paquet
- Comparative programming languages
- Alternative programming languages
- Types of programming languages
- Transmission programming languages
- Integral data type is
- Xenia programming languages
- Mainstream programming languages
- Programming languages
- Programming languages
- Programming languages
- Programming languages
- Language
- Brief history of programming languages
- Taxonomy of programming languages