Presentation is loading. Please wait.

Presentation is loading. Please wait.

Compiler Principles Fall 2014-2015 Compiler Principles Lecture 8: Intermediate Representation Roman Manevich Ben-Gurion University.

Similar presentations


Presentation on theme: "Compiler Principles Fall 2014-2015 Compiler Principles Lecture 8: Intermediate Representation Roman Manevich Ben-Gurion University."— Presentation transcript:

1 Compiler Principles Fall 2014-2015 Compiler Principles Lecture 8: Intermediate Representation Roman Manevich Ben-Gurion University

2 Tentative syllabus Front End Scanning Top-down Parsing (LL) Bottom-up Parsing (LR) Intermediate Representation Lowering Optimizations Local Optimizations Dataflow Analysis Loop Optimizations Code Generation Register Allocation Instruction Selection 2 mid-termexam

3 Previously Why compilers need Intermediate Representations (IR) Translating from abstract syntax (AST) to IR – Three-Address Code Local optimizations – Sethi-Ullman algorithm for efficient code generation 3

4 cgen for basic expressions 4 cgen(k) = { // k is a constant Choose a new temporary t Emit( t := k ) Return t { cgen(id) = { // id is an identifier Choose a new temporary t Emit( t := id ) Return t {

5 Naive cgen for binary expressions Maintain a counter for temporaries in c Initially: c = 0 cgen(e 1 op e 2 ) = { Let A = cgen(e 1 ) c = c + 1 Let B = cgen(e 2 ) c = c + 1 Emit( _tc := A op B; ) Return _tc } 5 The translation emits code to evaluate e 1 before e 2. Why is that?

6 Example: cgen for binary expressions 6 cgen( (a*b)-d)

7 Example: cgen for binary expressions 7 c = 0 cgen( (a*b)-d)

8 Example: cgen for binary expressions 8 c = 0 cgen( (a*b)-d) = { Let A = cgen(a*b) c = c + 1 Let B = cgen(d) c = c + 1 Emit( _tc := A - B; ) Return _tc }

9 Example: cgen for binary expressions 9 c = 0 cgen( (a*b)-d) = { Let A = { Let A = cgen(a) c = c + 1 Let B = cgen(b) c = c + 1 Emit( _tc := A * B; ) Return tc } c = c + 1 Let B = cgen(d) c = c + 1 Emit( _tc := A - B; ) Return _tc }

10 Example: cgen for binary expressions 10 c = 0 cgen( (a*b)-d) = { Let A = { Let A = { Emit(_tc := a;), return _tc } c = c + 1 Let B = { Emit(_tc := b;), return _tc } c = c + 1 Emit( _tc := A * B; ) Return _tc } c = c + 1 Let B = { Emit(_tc := d;), return _tc } c = c + 1 Emit( _tc := A - B; ) Return _tc } Code here A=_t0

11 Example: cgen for binary expressions 11 c = 0 cgen( (a*b)-d) = { Let A = { Let A = { Emit(_tc := a;), return _tc } c = c + 1 Let B = { Emit(_tc := b;), return _tc } c = c + 1 Emit( _tc := A * B; ) Return _tc } c = c + 1 Let B = { Emit(_tc := d;), return _tc } c = c + 1 Emit( _tc := A - B; ) Return _tc } Code _t0:=a; here A=_t0

12 Example: cgen for binary expressions 12 c = 0 cgen( (a*b)-d) = { Let A = { Let A = { Emit(_tc := a;), return _tc } c = c + 1 Let B = { Emit(_tc := b;), return _tc } c = c + 1 Emit( _tc := A * B; ) Return _tc } c = c + 1 Let B = { Emit(_tc := d;), return _tc } c = c + 1 Emit( _tc := A - B; ) Return _tc } Code _t0:=a; _t1:=b; here A=_t0

13 Example: cgen for binary expressions 13 c = 0 cgen( (a*b)-d) = { Let A = { Let A = { Emit(_tc := a;), return _tc } c = c + 1 Let B = { Emit(_tc := b;), return _tc } c = c + 1 Emit( _tc := A * B; ) Return _tc } c = c + 1 Let B = { Emit(_tc := d;), return _tc } c = c + 1 Emit( _tc := A - B; ) Return _tc } Code _t0:=a; _t1:=b; _t2:=_t0*_t1 here A=_t0

14 Example: cgen for binary expressions 14 c = 0 cgen( (a*b)-d) = { Let A = { Let A = { Emit(_tc := a;), return _tc } c = c + 1 Let B = { Emit(_tc := b;), return _tc } c = c + 1 Emit( _tc := A * B; ) Return _tc } c = c + 1 Let B = { Emit(_tc := d;), return _tc } c = c + 1 Emit( _tc := A - B; ) Return _tc } Code _t0:=a; _t1:=b; _t2:=_t0*_t1 here A=_t0 here A=_t2

15 Example: cgen for binary expressions 15 c = 0 cgen( (a*b)-d) = { Let A = { Let A = { Emit(_tc := a;), return _tc } c = c + 1 Let B = { Emit(_tc := b;), return _tc } c = c + 1 Emit( _tc := A * B; ) Return _tc } c = c + 1 Let B = { Emit(_tc := d;), return _tc } c = c + 1 Emit( _tc := A - B; ) Return _tc } Code _t0:=a; _t1:=b; _t2:=_t0*_t1 _t3:=d; here A=_t0 here A=_t2

16 Example: cgen for binary expressions 16 c = 0 cgen( (a*b)-d) = { Let A = { Let A = { Emit(_tc := a;), return _tc } c = c + 1 Let B = { Emit(_tc := b;), return _tc } c = c + 1 Emit( _tc := A * B; ) Return _tc } c = c + 1 Let B = { Emit(_tc := d;), return _tc } c = c + 1 Emit( _tc := A - B; ) Return _tc } Code _t0:=a; _t1:=b; _t2:=_t0*_t1 _t3:=d; _t4:=_t2-_t3 here A=_t0 here A=_t2

17 Naïve translation cgen translation shown so far very inefficient – Generates (too) many temporaries – one per sub- expression – Generates many instructions – at least one per sub-expression Expensive in terms of running time and space Code bloat We can do much better 17

18 agenda Lowering optimizations – Sethi-Ullman algorithm for efficient code generation 18

19 19 Lowering optimization

20 Improving cgen for expressions 1.Improve translation for leaves 2.Reuse temporaries 3.Weighted register allocation for expression trees – Reorder computations 20

21 21 Optimization 1: leaves

22 Improving cgen for leaves cases Observation – naïve translation needlessly generates temporaries for leaf expressions Solution: treat leaves as special cases by returning them immediately without storing them in temporaries 22

23 23 Optimization 2: reusing temporaries

24 cgen with temporaries recycling Observation – temporaries used exactly once – Once a temporary has been read it can be reused for another sub-expression Want to implement cgen(x := e 1 op e 2 ) with small number of temporaries cgen(x := e 1 op e 2 ) = { c = 0 Emit(x := cgen(e 1 op e 2 )) } 24 How can we make this more efficient?

25 Improved cgen c = 0 cgen(e 1 op e 2 ) = { cgen(e 1 ) c = c + 1 cgen(e 2 ) c = c - 1 Emit( _tc := _tc op _tc+1; ) } 25

26 Example 26 c = 0 cgen( (a*b)-d) = { { { Emit(_tc := a;), return _tc } c = c + 1 { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) } c = c + 1 { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) } Code c=0

27 Example 27 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; c=1

28 Example 28 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; _t1:=b; c=1

29 Example 29 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; _t1:=b; c=0

30 Example 30 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; _t1:=b; _t0:=_t0*_t1 c=0

31 Example 31 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; _t1:=b; _t0:=_t0*_t1; c=1

32 Example 32 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; _t1:=b; _t0:=_t0*_t1; _t1:=d; c=1

33 Example 33 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; _t1:=b; _t0:=_t0*_t1; _t1:=d; c=0

34 Example 34 c = 0 cgen( (a*b)-d) = { Let _tc = { Let _tc = { Emit(_tc := a;), return _tc } c = c + 1 Let _tc = { Emit(_tc := b;), return _tc } c = c - 1 Emit( _tc := _tc * _tc+1; ) Return _tc } c = c + 1 Let _tc = { Emit(_tc := d;), return _tc } c = c - 1 Emit( _tc := _tc - _tc+1; ) Return _tc } Code _t0:=a; _t1:=b; _t0:=_t0*_t1; _t1:=d; _t0:=_t0-_t1; c=0

35 Example 2 _t0 := cgen( ((c*d)-(e*f))+(a*b) ) _t0 := c*d _t1 := e*f _t0 := _t0 -_t1 c = c + 1 c = c - 1 c = 0 _t0 := cgen(c*d)-(e*f)) _t1 := a*b c = c + 1 _t0 := _t0 + _t1 c = c - 1 35

36 36 Optimization 3: weighted register allocation

37 Sethi-Ullman translation Algorithm by Ravi Sethi and Jeffrey D. Ullman to emit optimal TAC – Minimizes number of temporaries – (Minimizes number of instructions by reducing spills) – A kind of local register allocation (within single expressions) Uses two ideas 1.Reusing temporaries 2.Choosing order of translation 37

38 Weighted register allocation Suppose we have expression e 1 op e 2 – e 1, e 2 without side-effects That is, no function calls, memory accesses, ++x – Does order of translation matter? … Yes Sethi & Ullman’s algorithm translates heavier sub-tree first – Optimal local (per-statement) allocation for side- effect-free statements 38

39 Example 1 (assuming leaves require temporaries) _t0 := cgen( a+(b+(c*d)) ) b cd * + + a _t0 _t1 _t2 4 temporaries _t2 _t1 left child first b cd * + + a _t0 2 temporaries _t0 right child first _t0 39 _t1 _t3

40 Sethi-Ullman: weighted register allocation Can save registers by re-ordering subtree computations Phase 1: check that no side-effects exist and otherwise revert to translation following pre-defined order of computation Phase 2: assign weight to each node – Weight = number of registers needed – Leaf weight known – Internal node weight w(left) > w(right) then w = left w(right) > w(left) then w = right w(right) = w(left) then w = left + 1 Phase 3: translate by following heavier child first 40

41 Sethi-Ullman algorithm example cgen( g := (a+b)+((c+d)+(e+f))) ef + + + 41 ab + w=1 w=2w=1 w=2w=3 Code _t0 := c; _t1 := d; _t0 := _t0 * _t1; _t1 := e; _t2 := f; _t1 := _t1 * _t2; _t0 := _t0 - _t1 _t1 := a; _t2 := b; _t1 := _t1 -_t2 _t0 := _t1 - _t0 g := _t0 cd + w=1 w=2

42 Example with side effects b 5c * array access + a baseindex w=1 w=2w=1w=2 Phase 1: check absence of side-effects in expression tree Phase 2: assign weight to each AST node 42 _t0 := cgen( a+b[5*c] )

43 Example with side effects b 5c * array access + a _t0 baseindex W=2 Phase 2: use weights to decide on order of translation Heavier sub-tree _t0 := _t1 * _t0 _t0 := _t1[_t0] _t0 := _t1 + _t0 43 _t0 := cgen( a+b[5*c] ) w=1 w=2w=1w=2 _t0_t1 _t0 := c _t1 := 5 _t1 := b _t1 := a

44 Note on weighted register allocation The algorithm is local – works for a single expression Must reset temporaries counter after every statement: – x := y; y := z; should not be translated to _t0 := y; x := _t0; _t1 := z; y := _t1; – But rather to _t0 := y; x := _t0; # Finished translating statement. Set c=0 _t0 := z; y := _t0; 44

45 Going beyond the basic SU algorithm There exist advanced extensions of SU – Take into account semantics of operators – Take into account latency 45

46 Can we do better than basic SU here? cgen( g := (a+b)+((c+d)+(e+f))) ef + + + 46 ab + w=1 w=2w=1 w=2w=3 Code _t0 := c; _t1 := d; _t0 := _t0 + _t1; _t1 := e; _t2 := f; _t1 := _t1 + _t2; _t0 := _t0 + _t1 _t1 := a; _t2 := b; _t1 := _t1 +_t2 _t0 := _t1 + _t0 g := _t0 cd + w=1 w=2 What if we are allowed to rewrite expressions?

47 Can we do better than basic SU here? cgen( g := (a+b)+((c+d)+(e+f))) = cgen( g := a + (b + (c + (d + (e + f))))) + + 47 a Code _t0 := e; _t1 := f; _t0 := _t0 + _t1; _t1 := d; _t0 := _t0 + _t1; _t1 := c; _t0 := _t0 + _t1; _t1 := b; _t0 := _t0 + _t1; _t1 := a; _t0 := _t0 + _t1; g := _t0 +b +c +d fe w=1 w=2w=1w=2w=1w=2w=1w=2w=1w=2 Can rewrite since + is associative and commutative

48 Next lecture: Local Optimizations


Download ppt "Compiler Principles Fall 2014-2015 Compiler Principles Lecture 8: Intermediate Representation Roman Manevich Ben-Gurion University."

Similar presentations


Ads by Google