simple code generation cs153: compilers. code generation next ps: map fish code to mips code issues:...

34
Simple Code Generation CS153: Compilers

Upload: allan-francis

Post on 04-Jan-2016

225 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Simple Code Generation

CS153: Compilers

Page 2: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Code Generation• Next PS: Map Fish code to MIPS code• Issues:

– eliminating compound expressions– eliminating variables– encoding conditionals, short-circuits, loops

Page 3: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Source

type exp = Var of var| Int of int| Binop of exp * binop * exp| Not of exp| Or of exp * exp| And of exp * exp

Page 4: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Source

type stmt = Exp of exp | Assign of var * exp | Seq of stmt * stmt | If of exp * stmt * stmt | While of exp * stmt | For of exp * exp * exp * stmt | Return of exp

Page 5: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Target: MIPS

type label = string

type reg = R0 | R1 | R2 | … | R31

type operand = Reg of reg | Immed of word

Page 6: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

MIPS continuedtype inst = Add of reg * reg * operand | Li of reg * word | Slt of reg * reg * operand | Beq of reg * reg * label | Bgez of reg * label | J of label | La of reg * label | Lw of reg * reg * word | Sw of reg * reg * word | Label of label | ...

Page 7: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

VariablesFish only has global variables.

These can be placed in the data segment.

.data

.align 0x: .word 0y: .word 0z: .word 0

Page 8: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Variable Access

To compile x = x+1

la $3, x ; load x's address

lw $2, 0($3) ; load x's value

addi $2,$2,1 ; add 1

sw $2, 0($3) ; store value in x

Page 9: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

First Problem: Nested Expr's• Source:

– Binop(Binop(x,Plus,y),Plus,Binop(w,Plus,z))• Target:

– add rd, rs, rt

What should we do?

Page 10: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

A Simple Strategy• Given: Binop(A,Plus,B)• translate A so that result ends up in a

particular register (e.g., $3)• translate B so that result ends up in a

different register (e.g., $2)• Generate: add $2, $3, $2

Problems?

Page 11: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Strategy Fixed:• Invariants:

– results always placed in $2• Given: Binop(A,Plus,B)• translate A• save $2 somewhere• translate B• Restore A's value into register $3• Generate: add $2, $3, $2

Page 12: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

For example:

Binop(Binop(x,Plus,y),Plus,Binop(w,Plus,z))

1. compute x+y, placing result in $2

2. store result in a temporary t1

3. compute w+z, placing result in $2

4. load temporary t1 into a register, say $3

5. add $2, $3, $2

Page 13: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Expression Compilationlet rec exp2mips(e:exp):inst list = match e with | Int j -> [Li(R2, Word32.fromInt j)] | Var x -> [La(R2,x), Lw(R2,R2,zero)] | Binop(e1,b,e2) -> (let t = new_temp()in (exp2mips e1) @ [La(R1,t), Sw(R2,R1,zero)]

@(exp2mips e2) @ [La(R1,t), Lw(R1,R1,zero)] @(match b with Plus -> [Add(R2,R2,Reg R1)] | ... -> ...))

| Assign(x,e) => [exp2mips e] @ [La(R1,x), Sw(R2,R1,zero)]

Page 14: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Statements let rec stmt2mips(s:stmt):inst list = match s with | Exp e -> exp2mips e | Seq(s1,s2) ->

(stmt2mips s1) @ (stmt2mips s2) | If(e,s1,s2) -> (let else_l = new_label() in

let end_l = new_label() in (exp2mips e) @ [Beq(R2,R0,else_l)] @ (stmt2mips s1) @ [J end_l,Label else_l] @ (stmt2mips s2) @ [Label end_l])

Page 15: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Statements Continued | While(e,s) -> (let test_l = new_label() in let top_l = new_label() in

[J test_l, Label top_l] @ (stmt2mips s) @ [Label test_l] @ (exp2mips e) @ [Bne(R2,R0,top_l)])

| For(e1,e2,e3,s) -> stmt2mips(Seq(Exp e1,While(e2,Seq(s,Exp e3))))

Page 16: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Lots of Inefficiencies:• No constant folding.• For "if (x == y) s1 else s2" we do a seq followed by a beq when we could just do a beq.

• For "if (b1 && b2) s1 else s2" we could just jump to s2 when b1 is false.

• Lots of la/lw and la/sw for variables.• For e1 + e2, we always write out e1's value to

memory when we could just cache it in a register.

Page 17: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Append:Naïve append:

fun append [] y = y | append (h::t) y = h::(append t y)

Tail-recursive append:

fun revapp [] y = y | revapp (h::t) y = revapp t (h::y)fun rev x = revapp x []fun append x y = revapp (rev x) y

Page 18: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Accumulater-Based:let rec exp2mips’(e:exp) (a:inst list):inst list = match e with Int w -> Li(R2, Word32.fromInt w) :: a | Var x -> revapp [La(R2,x), Lw(R2,R2,zero)] a | Binop(e1,b,e2) => (let t = new_temp() in exp2mips’ e1 (revapp [La(R1,t), Sw(R2,R1,zero)] (exp2mips’ e2 (revapp [La(R1,t), Lw(R1,R1,zero)] ((match b with Plus -> Add(R2,R2,Reg R1) | ... -> ...) ::a)))))

let exp2mips (i:exp) = rev(exp2mips' i [])

Page 19: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Constant Folding: Take 1let rec exp2mips’(e:exp) (a:inst list) = match e with Int w -> Li(R2, Word32.fromInt w) :: a | Binop(e1,Plus,Int 0) -> exp2mips’ e1 a | Binop(Int i1,Plus,Int i2) -> exp2mips' (Int (i1+i2)) a | Binop(Int i1,Minus,Int i2) -> exp2mips' (Int (i1-i2)) a | Binop(e1,b,e2) -> ...

Why isn't this great? How can we fix it?

Page 20: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Conditional ContextsConsider: if (x < y) then S1 else S2

slt $2, $2, $3 beq $2 $0, ELSE

[instructions for S1] j END

ELSE: [instructions for S2]

END:

Page 21: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Observation• In most contexts, we want a value.• But in a testing context, we jump to one

place or another based on the value, and otherwise never use the value.

• In many situations, we can avoid materializing the value and thus produce better code.

Page 22: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

For Example:let rec bexp2mips(e:exp) (t:label) (f:label) = match e with Int 0 -> [J f] | Int _ -> [J t] | Binop(e1,Eq,e2) => (exp2mips e1) @ [La(R1,t), Sw(R2,R1,zero)] @ (exp2mips e2) @ [La(R1,t), Lw(R1,R1,zero), Bne(R1,R2,f), J t] | _ -> (exp2mips e1) @ [ Beq(R2,R0,f), J t ]

Page 23: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Global Variables:We treated all variables (including temps)

as if they were globals:– set aside data with a label– to read: load address of label, then load

value stored at that address.– to write: load address of label, then store

value at that address.

This is fairly inefficient:– e.g., x+x involves loading x's address twice!– lots of memory operations.

Page 24: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Register Allocation:• One option is to allocate a register to hold

a variable's value:– Eliminates the need to load an address or do

memory operations.– Will talk about more generally later.– Of course, in general, we can't avoid it when

code has more (live) variables than registers. • Can we at least avoid loading addresses?

Page 25: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Frames:• Set aside one block of memory for all of

the variables.• Dedicate $30 (aka $fp) to hold the base

address of the block.• Assign each variable a

position within the block(x0, y4, z8, etc.)

• Now loads/stores can bedone relative to $fp:

x

y

z

Page 26: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Before and After:z = x+1

la $1,xlw $2,0($1)addi $2,$2,1la $1,zsw $2,0($1)

lw $2,0($fp) addi $2,$2,1 sw $2,8($fp)

Page 27: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Lowering• Get rid of nested expressions before

translating– Introduce new variables to hold intermediate

results– Perhaps do things like constant folding

• For example, a = (x + y) + (z + w) might be translated to:t0 := x + y;t1 := z + w;a := t0 + t1;

Page 28: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

12 instructions (9 memory)t0 := x + y; lw $v0, <xoff>($fp)

lw $v1, <yoff>($fp)add $v0, $v0, $v1sw $v0, <t0off>($fp)

t1 := z + w; lw $v0, <zoff>($fp)lw $v1, <woff>($fp)add $v0, $v0, $v1sw $v0, <t1off>($fp)

a := t0 + t1; lw $v0, <t0off>($fp)lw $v1, <t1off>($fp)add $v0, $v0, $v1sw $v0, <aoff>($fp)

Page 29: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Still…We're doing a lot of stupid loads and stores.

– We shouldn't need to load/store from temps!– (Nor variables, but we'll deal with them later…)

So another idea is to use registers to hold the intermediate values instead of variables.– Of course, we can only use registers to hold some

number of temps (say k).– Maybe use registers to hold first k temps?

Page 30: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

For example:t0 := x; # load variablet1 := y; # load variablet2 := t0 + t1;# addt3 := z; # load variablet4 := w; # load variablet5 := t3 + t4; # addt6 := t2 + t5;# adda := t6; # store result

Page 31: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Then: 8 instructions (5 mem!)• Notice that each little statement can be directly

translated to MIPs instructions:t0 := x; --> lw $t0,<xoff>($fp)t1 := y; --> lw $t1,<yoff>($fp)t2 := t0 + t1; --> add $t2,$t0,$t1t3 := z; --> lw $t3,<zoff>($fp)t4 := w; --> lw $t4,<woff>($fp)t5 := t3 + t4; --> add $t5,$t3,$t4t6 := t2 + t5; --> add $t6,$t2,$t5a := t6; --> sw $t6,<aoff>($fp)

Page 32: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Recycling:• Sometimes we can recycle a temp:

t0 := x; t0 takent1 := y; t0,t1 takent2 := t0 + t1; t2 taken (t0,t1 free)t3 := z; t2,t3 takent4 := w; t2,t3,t4 takent5 := t3 + t4; t2,t5 taken (t3,t4 free)t6 := t2 + t5; t6 taken (t2,t5 free)a := t6; (t6 free)

Page 33: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Tracking Available Temps:Hmmm. Looks a lot like a stack…

t0 := x; t0t1 := y; t1,t0t0 := t0 + t1; t0t1 := z; t1,t0t2 := w; t2,t1,t0t1 := t1 + t2; t1,t0t1 := t0 + t1; t1a := t1; <empty>

Page 34: Simple Code Generation CS153: Compilers. Code Generation Next PS: Map Fish code to MIPS code Issues: –eliminating compound expressions –eliminating variables

Finally, consider:

(x+y)*x

t0 := x; # loads xt1 := y; t0 := x+y t1 := x; # loads x again!t0 := t0*t1;