Compiler Design Spring 2018 2.3 Templates (for code generation) - - PowerPoint PPT Presentation

compiler design
SMART_READER_LITE
LIVE PREVIEW

Compiler Design Spring 2018 2.3 Templates (for code generation) - - PowerPoint PPT Presentation

Compiler Design Spring 2018 2.3 Templates (for code generation) 2.4 Template-based code generator Thomas R. Gross Computer Science Department ETH Zurich, Switzerland 26 2.3 Templates Templates decide how code generator behaves


slide-1
SLIDE 1

Compiler Design

Spring 2018 2.3 Templates (for code generation) 2.4 Template-based code generator

26

Thomas R. Gross Computer Science Department ETH Zurich, Switzerland

slide-2
SLIDE 2

2.3 Templates

§ Templates decide how code generator behaves

§ “Quality” of code

§ Decide how each kind of IR node is handled

§ Simple (for now) § Minimal solution (for now)

§ Next: Produce a catalogue of templates

27

slide-3
SLIDE 3

Ground rules

§ Set of rules to guide template design § Reflect machine properties and/or desire to keep CG simple

§ You could define your own rules

§ Rules for now:

1. All templates leave result in a register

§ Exception: ASSIGN nodes have no return value

2. All operands must be in a register

§ Lots of memory traffic for 32-bit x86 § Other options: (1) At least one operand must be in a register (2) At most one operand can be in memory

28

slide-4
SLIDE 4

Data structures

§ reg_pool: Pool (list) of free registers § Methods

§ get_register() § free_register(Register register)

29

slide-5
SLIDE 5

2.3.1 CONST

§ Value must be put into reg § Template

// bookkeeping // get a new register reg = reg_pool.getRegister() // code generation emit “movl $0x…, reg” // no more bookkeping return reg;

30

value v 0x…: hexadecimal representation of v

slide-6
SLIDE 6

Potential problems

§ No register in reg_pool

§ Not today

§ Value ’v’ does not fit into movl instruction

§ v requires more than 32 bits § v exceeds limit of immediate in instruction

§ Options

§ Delegate problem to assembler

§ Can break v into pieces, shift/assembly in register

§ Allocate entry in .data segment, load from memory § Require that IR contains only constants that fit into movl

§ Front-end must deal with problem § Homework #1: Assume only values that fit

31

slide-7
SLIDE 7

2.3.2 VAR

§ Recall:

§ VAR node on the left hand side of ASSIGN: delivers an address § VAR node on the right hand side of ASSIGN (anywhere in tree): delivers a value

§ Value is kept in a memory location (known to the compiler) § Later: Other storage classes

32

slide-8
SLIDE 8

VAR (at RHS)

§ Value must be put into register

§ Similar to CONST node

§ Template

// bookkeeping // get a new register reg = reg_pool.getRegister() // code generation emit “movl name, reg” // name identifies location // no more bookkeping return reg;

33

slide-9
SLIDE 9

Comment

§ Assume name maps to a known location

§ Various addressing modes exist § For now: Simple scheme is sufficient

34

slide-10
SLIDE 10

VAR (at LHS)

§ Must deliver an address

§ For now: Enough to deliver a name

§ Template: Let parent use the name

§ Assume we have a method that returns the name for a VAR node § Only user so far: ASSIGN

35

slide-11
SLIDE 11

37

slide-12
SLIDE 12

OPERATOR

§ Result must be put into reg § Assume left and right evaluated into a register

§ reg_right § reg_left

§ Reuse one of the registers to hold result

§ Take reg_right

§ Free other register

§ No longer needed: reg_left

38

OP +

right

register reg_right

left

register reg_left

slide-13
SLIDE 13

OPERATOR

§ Template

// bookkeeping // code generation emit “OP[Operator].txt reg_left, reg_right” // bookkeeping // free reg_left reg_pool.free_register(reg_left) // no more bookkeping return reg_right;

§ Could ask for a new register

§ Benefit: Keeps around values for longer § Not really an option with 32-bit x86 (limited # of registers)

39

slide-14
SLIDE 14

2.3.4 ASSIGN

§ Value must be put into reg § Left hand side: Destination for a (named) variable

§ We can get the variable name § Use variable name in assembly instruction

§ Right hand side: result in register § No “return value”

40

=

VAR

A

right

register reg_right Memory location of variable A

slide-15
SLIDE 15

2.3.4 ASSIGN

§ Template

// preparation // code generation emit “movl reg_right, name” // bookkeeping // free reg_right reg_pool.free_register(reg_right) // no more bookkeping return null;

41

slide-16
SLIDE 16

2.4 Putting the CG together

§ Code for children must be generated before code for parents can be generated § codegen(Node n) { … }

§ Start with codegen(Root)

§ codegen(Node n)

§ Leafnode? Generate code § Not leafnode? Visit children

§ In which order?

§ Code for node n

43

slide-17
SLIDE 17

Skeleton

Register codegen(Node n) { Register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: } }

45

slide-18
SLIDE 18

Right child first

Register codegen(Node n) { Register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: { reg_right = codegen(N.right_child); reg_left = codegen(N.left_child); // Template 2.3.3 return reg_right; } } }

46

slide-19
SLIDE 19

47

slide-20
SLIDE 20

48

slide-21
SLIDE 21

How does it work?

§ Examples

§ a = 1 § a = b + c § x = b + c + d + e

50

slide-22
SLIDE 22

52

slide-23
SLIDE 23

56

slide-24
SLIDE 24

Compiler Design

Spring 2018 2.5 Dynamic programming code generation

1

Thomas R. Gross Computer Science Department ETH Zurich, Switzerland

slide-25
SLIDE 25

Motivation: Recall “right child first”

Register codegen(Node n) { register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: { reg_right = codegen(N.right_child); reg_left = codegen(N.left_child); // Template 2.3.3 return reg_right; } } }

2

slide-26
SLIDE 26

Discussion

§ We decided to

§ Use reg_right for the result of an operation § We decided to visit the right subtree first

§ We could have decided to

§ Visit the left subtree first § (Use reg_left for the result of an operation – won’t show that here)

8

slide-27
SLIDE 27

Left child first

Register codegen(Node n) { register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: { reg_left = codegen(N.left_child); reg_right = codegen(N.right_child); // Template 2.3.3 return reg_right; } } }

9

slide-28
SLIDE 28

How does it work (left-first)

§ Example

§ a = b + c + d + e

10

slide-29
SLIDE 29

11

slide-30
SLIDE 30

12

slide-31
SLIDE 31

14

a = b + c + d + e reg_pool = {%eax,%ebx,%ecx,%edx}

slide-32
SLIDE 32

Discussion

§ Using a smaller number of registers is better than using a larger number of registers

§ Right child first: 2 registers (%eax, %ebx) § Left child first: 4 registers (%eax, %ebx, %ecx, %edx)

§ Should we forget about “left child first”?

16

slide-33
SLIDE 33

No evaluation order is the best

Find an assignment statement (with only + as operand and four

  • perands on the right hand side) such that for this statement the

“visit left child first” strategy delivers a better result (smaller number of registers is needed) than the “visit right child first” strategy. You can jump right to the tree if you wish.

17

slide-34
SLIDE 34

No evaluation order is the best

§ Example

§ x = (((z + w) + y) + v)

18

slide-35
SLIDE 35

No evaluation order is the best

Left child first

19

= x * v + + y z w

slide-36
SLIDE 36

20

slide-37
SLIDE 37

No evaluation order is the best

Right child first

21

= x * v + + y z w

slide-38
SLIDE 38

No evaluation order is the best

§ No strategy is best for all possible trees § Decide for each node how children should be evaluated § Idea: 2-step approach

Step 1: Determine strategy

§ Visit node § Determine which order is best (uses the smallest number of registers) § Record order (right first or left first)

Step 2: Generate code

§ Visit node § Look at result from first step to fix evaluation order

24

slide-39
SLIDE 39

Dynamic programming code generation

§ Step 1 must determine both the number of registers needed and the evaluation order

§ need: number of registers § right_first: boolean (true/false)

§ If no difference, favor right first

§ We must make some assumptions

25

slide-40
SLIDE 40

Simplifications (in machine model)

§ Assumptions

§ All registers are equal § All operations deliver result into a register § All operands/results require a single register § No optimizations (reuse of operands)

§ Real machines do not always meet these assumptions

§ Some offer new opportunities § Example: Take one operand from memory (later)

26

slide-41
SLIDE 41

2.5 Dynamic programming code generation

§ Step 1 must determine both the number of registers needed and the evaluation order

§ need: number of registers § right_first: boolean (true/false)

§ If no difference, favor right first

§ Four kinds of nodes to consider

§ VAR: need = 1 § CONST: need = 1 § ASSIGN: need determined by right child § OPERATOR: see next slide

27

slide-42
SLIDE 42

28

slide-43
SLIDE 43

Key idea

§ To get smallest number of registers:

§ Evaluate larger subtree (expression) first § Keep result in register

§ Recall assumptions

§ All registers created equally

29

slide-44
SLIDE 44

OPERATOR node

§ Case 1: right_child.need > left_child.need

§ right_first = § need =

§ Case 2: right_child.need < left_child.need

§ right_first = § need =

§ Case 3: right_child.need == left_child.need

§ right_first = § need =

30

slide-45
SLIDE 45

OPERATOR node

§ Case 1: right_child.need > left_child.need

§ right_first = true § need = right_child.need

§ Case 2: right_child.need < left_child.need

§ right_first = false § need = left_child.need

§ Case 3: right_child.need == left_child.need

§ right_first = true § need = right_child.need + 1

31

slide-46
SLIDE 46

Big picture

§ Idea: 2-step approach

Step 1: Determine strategy

§ Visit node § Determine which order is best (uses the smallest number of registers) § Record order (right first or left first)

Step 2: Generate code

§ Visit node § Look at result from first step to fix evaluation order

34

slide-47
SLIDE 47

Step 2

Register codegen(Node n) {

register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1

OP: { if (right_first) { reg_right = codegen(N.right_child); reg_left = codegen(N.left_child); } else { // left first reg_left = codegen(N.left_child); reg_right = codegen(N.right_child); }

// Template 2.3.3 return reg_right; } } }

35

slide-48
SLIDE 48

How does it work?

§ Example

§ x = (((a + b) + (h + j)) + d) + (e + (f + g))

36

slide-49
SLIDE 49

37

slide-50
SLIDE 50

What to do if there are not enough registers?

§ Punt it

§ OK for Homework 1 if the compiler exits gracefully

§ Other approaches (not required by Homework 1)

§ Free register

§ Later recompute (“rematerialize”) § Temporarily store value in memory (“spill”) – usually on stack

§ Restructure the tree

§ Recall that this step may change the semantics

41

slide-51
SLIDE 51

Restructuring trees : x = b + c + d + e

x = b + c + d + e x = b + c + d + e

42

= x + + b c + d e = x + + + b e c d

slide-52
SLIDE 52

43

slide-53
SLIDE 53

What to do if there are not enough registers?

§ Punt it

§ OK for Homework 1 if the compiler exits gracefully

§ Other approaches (not required by Homework 1)

§ Free register

§ Later recompute (“rematerialize”) § Temporarily store value in memory (“spill”) – usually on stack

§ Restructure the tree

§ Recall that this step may change the semantics

§ Use special instructions § Leave some operand in memory

§ See next slides on code generator improvements

45

slide-54
SLIDE 54

Improvements to the code generator

§ Idea: Look at target machine and try to find special instructions that cover more than one IR node § Produce better code

§ Fewer registers needed § Fewer instructions: Shorter code, (possibly) reduced execution time

46

slide-55
SLIDE 55

Improvement #1

§ Some machines have an “increment” operation

§ E.g., inc on 32-bit x86

§ Example: x = x + 1

47

Generated code movl 0x1, %rax movl x, %rbx addl %rbx, %rax + x 1 … Improved code movl x, %rax inc %rax

slide-56
SLIDE 56

Implementation

§ Extend template catalogue

§ Subcases for existing template § New templates

§ For OPERATOR: Look for CONST child

§ Possible restrictions on value § For addition/subtraction: allow 1/-1 § For multiplication: maybe allow 1, 2, 4, 8

§ Limit: your willingness to deal with details

49

slide-57
SLIDE 57

Improvement #2

§ Observation: Some machines allow one operand in memory

§ E.g., on x86 the following instructions are available

ADD register, memory ADD memory, register

§ (So far we’ve used only

ADD register, register)

§ Idea: Use special instruction to leave an operand in memory

50

slide-58
SLIDE 58

Example

So far: 2 operands in registers Improved: 1 operand in register

51

+ x + … … + x + … …

slide-59
SLIDE 59

Example

So far: 2 operands in registers Improved: 1 operand in register

53

+ x + … … %eax movl x, %ebx addl %ebx, %eax + x + … … %eax addl x, %eax %ebx

slide-60
SLIDE 60

Notes

§ Improvements not required by Homework 1

§ Goals of Homework 1: Correctness + ”optimal” # of registers § You can look into optimizations if you want

§ Emit code (instructions) to file

§ Or to a buffer § Can be processed before writing to file

§ Add hints to emitted code

§ IR node number § Line number that generated IR § Begin/end of a source language statement

54

slide-61
SLIDE 61

Some admin issues

§ Homework 1

§ Description / fragment out

§ There will be a recitation session today

§ Room: ETF E 1 § Starts at 15:00 § Discussion of Homework 1 (“Simple code generator”) § Discussion of Javali framework

55