cse322, programming languages and compilers 1 7/13/2015 lecture #2, april 5, 2007 overview of...

38
Cse322, Programming Languages and Compilers 1 06/23/22 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing), Translating arithmetic, Register allocation, Reducing demand for registers, Reuse of registers, List.find, Anonymous functions.

Post on 22-Dec-2015

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

104/19/23

Lecture #2, April 5, 2007• Overview of backend issues • (storage locations, registers, aliasing),•Translating arithmetic,•Register allocation,•Reducing demand for registers,•Reuse of registers,•List.find,•Anonymous functions.

Page 2: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

204/19/23

Assignments

• Reading– Read chapter 7 sections 7.4 and 7.5

– Possible Quiz next Monday on the reading.

• Programming assignment #1 is now available on the class website under the assignments link.

• PLEASE take note of this as this page is not in the handout.

Page 3: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

304/19/23

Over view of Back-end issues

• Code Shape– How to choose the correct shape for a language construct

» Case – cascading if then else, binary search, dispatch table

» Commutative associative operators

• Instruction Choice– Which assembly level instructions to use

• Register allocation– How to use registers vs memory

• Instruction scheduling– Reording instructions

Page 4: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

404/19/23

Assigning Storage Locations

• Lifetime and scope determine some storage issues

– Parameters

– Local variables

– Global variables

– Scoped variables

» Static scope in block structured languages

» Overridden instance variables in OO languages

– Un-named values (x+3) in y = (x+3) * z

Page 5: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

504/19/23

Registers

• Limited numbers, requires resource allocation

• Not all values fit in a register• Some variables (with short lifetimes) only

live in registers• Others need to be “stored” when the

register is needed for another purpose.• Locations whose “address” is needed (for

call by reference, or for pointer-to uses) cannot reside in registers.

Page 6: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

604/19/23

Aliasing• Sometimes there are more than 1 name for

a location.• Pointers

int a, *b;b = &a;

• Reference parameters int f(ref int a, ref int b) { int c; c := a; a := b; b := c }

call f(x,x)• Array References

Are x[i] and x[j-n] different?

Page 7: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

704/19/23

Translating Arithmetic

• Most machines have a full complement of arithmetic, logical, and shifting operations.

• Such operations are almost always register based.

• Translating requires.– Getting values in registers

– Choosing an order to perform operations

– Emitting instructions

• Subtleties– Using the fewest registers

– Constant folding ie. (x + 3 + 5) -> (x + 8)

Page 8: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

804/19/23

Consider

loadI @x => r1

loadAO rA,r1 => r2

loadI 2 => r3

loadI @y => r4

loadAO rA,r4 => r5

Mul r3,r5 => r6

Sub r2,r6 => r7

-

x *

2 y

loadAOload at offset

Page 9: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

904/19/23

Creating an algorithm

• Design data structures to hold source (expressions) and target code (IR).

• Decide how to treat registers

• Decide how to deal with generating IR sequences.

Page 10: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1004/19/23

Expressions• We will reuse the Exp datatype from CS321

datatype Exp = Literal of Constant (* 5, 6.3, true *)

| Binop of BINOP * Exp * Exp (* x + 3 *) | Var of Exp option * Id (* object.x, y *)

| Relop of RELOP * Exp * Exp (* x < 7.7 *) | Not of Exp (* ! x *) | ArrayElm of Exp * Exp * (Basic TC) (* x[3] *) | ArrayLen of Exp (* x.length() *) | Call of Exp * Id *(Id TC)* Exp list (* x.f(1,z) *) | NewArray of Basic * Exp (* new int[3] *) | NewObject of Id (* new point() *)

Page 11: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1104/19/23

IR and Registers

• We define a new ML datatype for IR– For today it will only have three general kinds of instructions

type Reg = int;

datatype IR

= LoadI of (string * Reg)

| LoadAO of (Reg * Reg * Reg)

| Arith of (BINOP * Reg * Reg * Reg);

datatype BINOP = ADD | SUB | MUL | DIV (* Arithmetic *) | AND | OR; (* logical *)

BINOP is reused from the CS321 as

well

Page 12: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1204/19/23

CompareThe abstract syntax

datatype IR = LoadI of (string * Reg) | LoadAO of (Reg * Reg * Reg) | Arith of (BINOP * Reg * Reg * Reg);

With the concrete syntax

loadI @x => r1loadAO rA,r1 => r2loadI 2 => r3loadI @y => r4loadAO rA,r4 => r5Mul r3,r5 => r6Sub r2,r6 => r7

Page 13: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1304/19/23

Computing the concrete Syntax• We can write a pattern matching ML program

to compute the concrete syntax from the datatype representing the abstract syntax.

• It is an ordinary pattern-matching ML program.

datatype IR = LoadI of (string * Reg) | LoadAO of (Reg * Reg * Reg) | Arith of (BINOP * Reg * Reg * Reg);

• We will need to write three parts– Converting registers to strings– Converting BINOP to strings– Converting IR itself to a string

Page 14: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1404/19/23

Registers to strings

type Reg = int;

fun showReg 0 = "rA"

| showReg n = "r"^Int.toString n;

• A register is just an integer, we can use the library function int.toString to turn it into a string

• We use the convention that register 0 is the activation record pointer, which we print as “rA”

• Other registers print the integer value preceded by “r”

Page 15: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1504/19/23

Op to string

• A very simple pattern match across the 6 cases.

fun showOp ADD = "Add "

| showOp SUB = "Sub "

| showOp MUL = "Mul "

| showOp DIV = "Div "

| showOp AND = "And "

| showOp OR = "Or "

Page 16: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1604/19/23

IR to string

• Note the extensive use of “^” the string concatenation function.

fun showIR (LoadI(s,r)) =

"loadI "^s^" => "^showReg r

| showIR (LoadAO(x,y,z)) =

"loadAO "^showReg x^","^showReg y^" => "^

showReg z

| showIR (Arith(m,x,y,z)) =

showOp m^" "^showReg x^","^

showReg y^" => "^showReg z;

Page 17: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1704/19/23

Emitting instructions

• Emitting instructions is an effect.• It is implicit in the functions “expr”, “base”,

and “offsett”.• Instructions are accumulated in the

reference variable “emitted”

val emitted = ref ([]: IR list);

fun emit x = emitted := (x :: (!emitted));

• Note that the instructions are accumulated in the reverse order they are emitted.

Page 18: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1804/19/23

Registers• Registers are nothing more than integers.• We need a way to allocate them incrementally• We need to be able to reset the allocation.

val Rarp = 0;val firstRegister = 1;val regCount = ref firstRegister;

fun resetRegister () = regCount := firstRegister;

fun NextRegister() = let val n = !regCount in (regCount := n+1; n) end;

Page 19: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

1904/19/23

Base and offsett

• We assume that all variables can be accessed as an offset from some base address.

• The function “base” loads the base address for a variable into a register by emitting the correct code and then returns the register.

• The function “offset” loads the offset into a register by emitting code, and then returns the register.

• For simplicity– The base address is always assumed stored in the activation

record pointer stored in register 0, which we write “ra”

– The offset is some constant we write as “@x” for variable “x”, i.e. the address or offset for “x”

– Later on we will relax these assumptions.

Page 20: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2004/19/23

fun offset (Var(_,x)) =

let val result = NextRegister()

in emit (LoadI("@"^x,result));

result

end;

fun base x = Rarp;

Page 21: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2104/19/23

Translationfun expr node =case node of Var(loc,x) => let val t1 = base node val t2 = offset node val result = NextRegister() in emit (LoadAO(t1,t2,result)); result end| Binop(m,x,y) => let val t1 = expr x val t2 = expr y val result = NextRegister() in emit (Arith(m,t1,t2,result)); result end| Literal(loc,Cint n) => let val result = NextRegister() in emit (LoadI(n,result)); result end

Page 22: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2204/19/23

Results

fun var x = (Var(NONE,x));

fun const n = Literal(Cint n);

val ex1 = Binop(SUB, (* x – (2 * y) *)

var "x",

Binop(MUL,

const 2,

var "y"));

Page 23: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2304/19/23

- trans ex1;

loadI @x => r1loadAO rA,r1 => r2loadI 2 => r3loadI @y => r4loadAO rA,r4 => r5Mul r3,r5 => r6Sub r2,r6 => r7

val it = [LoadI ("@x",1),LoadAO (0,1,2),LoadI ("2",3), LoadI ("@y",4),LoadAO (Arith (MUL,3,5,6), Arith (SUB,2,6,7)] : IR list

Page 24: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2404/19/23

The function trans

fun trans x =

let val _ = emitted := []

val _ = resetRegister ()

val result = expr x

val instrs = rev (!emitted)

val _ = print "\n";

fun sh x = print(showIR x^"\n")

val _ = map sh instrs

val _ = print "\n\n";

in instrs end;

Reset the emitted instructions and the next register counter

The emiited instructions

are collected in reverse order

Print the instructions

for the user to inspect

Page 25: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2504/19/23

Register Allocation

•Register allocation assigns physical registers to each logical registers. Think of it as a renaming, where we have a limited number of names.

•We can reuse a register after we have no further demands on it.

no further demand

loadI @x => r1 { }

loadAO rA,r1 => r2 {r1}

loadI 2 => r3 {r1}

loadI @y => r4 {r1}

loadAO rA,r4 => r5 {r1,r4}

Mul r3,r5 => r6 {r1,r3,r4,r5}

Sub r2,r6 => r7 {r1,r2,r3,r4,r5,r6}

Page 26: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2604/19/23

Immediate reuse.

loadI @x => r1

loadAO rA,r1 => r2

loadI 2 => r3

loadI @y => r4

loadAO rA,r4 => r5

Mul r3,r5 => r6

Sub r2,r6 => r7

loadI @x => r1

loadAO rA,r1 => r1

loadI 2 => r2

loadI @y => r3

loadAO rA,r3 => r3

Mul r2,r3 => r2

Sub r1,r2 => r2

Page 27: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2704/19/23

Can we do better?

• x – (2 * y)

• Loading x first (before computing (2 * y)) causes the lifetime of r2 to be very long.

• Suppose we translated (2*y) before x?

loadI @x => r1

loadAO rA,r1 => r2

loadI 2 => r3

loadI @y => r4

loadAO rA,r4 => r5

Mul r3,r5 => r6

Sub r2,r6 => r7

Page 28: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2804/19/23

Translating (2 * y) first

loadI @y => r1

loadAO rA,r1 => r2

loadI 2 => r3

Mul r2,r3 => r4

loadI @x => r5

loadAO rA,r5 => r6

Sub r4,r6 => r7

loadI @y => r1

loadAO rA,r1 => r1

loadI 2 => r2

Mul r2,r1 => r1

loadI @x => r2

loadAO rA,r2 => r2

Sub r2,r1 => r1

Before register allocation After register allocation

Page 29: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

2904/19/23

Compare

loadI @y => r1

loadAO rA,r1 => r1

loadI 2 => r2

Mul r2,r1 => r1

loadI @x => r2

loadAO rA,r2 => r2

Sub r2,r1 => r1

loadI @x => r1

loadAO rA,r1 => r1

loadI 2 => r2

loadI @y => r3

loadAO rA,r3 => r3

Mul r2,r3 => r2

Sub r1,r2 => r2

Translating x first translating (2 * y) first

Page 30: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3004/19/23

Rule of thumb

• To avoid tying up registers for a long time, we should translate subexpressions which are large first.

• How do we determine large?• An expression is larger than another

expression, it requires more registers to translate.

• Chicken an egg problem.– To translate we need to know how many registers

– To know how many registers we need to translate

– Solution

» Pre-processing

» Dynamic exploration

Page 31: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3104/19/23

Variable reuse.

• Consider translating x – (2 * x)

loadI @x => r1loadAO rA,r1 => r2loadI 2 => r3loadI @x => r4loadAO rA,r4 => r5Mul r3,r5 => r6Sub r2,r6 => r7

loadI @x => r1loadAO rA,r1 => r2loadI 2 => r3Mul r3,r2 => r4Sub r2,r4 => r5

loadI @x => r1loadAO rA,r1 => r1loadI 2 => r2Mul r2,r1 => r1Sub r2,r1 => r1

Register allocation

Page 32: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3204/19/23

How could we implement this?• If we kept a dictionary of which register (if

any) a variable resides in, we could try this first in the Var case of “expr”

case node of Var(loc,x) => let val t1 = base node val t2 = offset node val result = NextRegister() in emit (LoadAO(t1,t2,result)); result end

Page 33: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3304/19/23

Using the dictionaryfun expr2 dict node =

case node of

Var(loc,x) =>

(case List.find (fn (nm,r) => x=nm) (!dict) of

NONE => let val t1 = base node

val t2 = offset node

val result = NextRegister()

in emit (LoadAO(t1,t2,result));

dict := (x,result)::(!dict);

result

end

| SOME(x,r) => r)

Page 34: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3404/19/23

The List.find programming pattern

Case List.find (fn (nm,r) => x=nm) (!dict) of

NONE => …

| SOME(_,z) => …

• In SML we use library functions all the time.– Int.toString– List.find

• The List.find function is particularly useful.

– It takes a function as an argument– List.find : ('a -> bool) -> 'a list -> 'a option–

• It is worth studying this function closely

Page 35: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3504/19/23

Anonymous functions• Study: (fn x => (x+1))

– It is an anonymous function. A function without a name.– It has one parameter “x”– It adds one to its parameter, and returns the result.

(fn x => (x+1)) 4;val it = 5 : int

• Any non-recursive function can be written anonymously.– (fn x => x = 5)

» Tests if its parameter is equal to 5(fn x => x=5) 8;val it = false : bool;

– (fn x => fn y => (x,y))» Has two parameters» Returns a pair

– (fn (x,y) => (not y, x+3))» What is the type of this function?

Page 36: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3604/19/23

List.find

• Used for searching a list.– List.find : ('a -> bool) -> 'a list -> 'a option

• Uses a function as a parameter to determine if the search is successful.

• E.g. Is there an even element in a list?List.find even [1,3,5];

val it = NONE : int option

List.find even [1,3,4];

val it = SOME 4 : int option

Page 37: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3704/19/23

List.find and anonymous functions

List.find (fn x => x = "Tim")

["Tom", "Jane"];

val it = NONE : string option

List.find (fn x => even x andalso x>10)

[2,4,5,12];

val it = SOME 12 : int option

Page 38: Cse322, Programming Languages and Compilers 1 7/13/2015 Lecture #2, April 5, 2007 Overview of backend issues (storage locations, registers, aliasing),

Cse322, Programming Languages and Compilers

3804/19/23

Assignment #1CS322 Prog Lang & Compilers Prog Assignment #1Assigned Wednesday April 5, 2007. Due Monday, April 10, 2007

This assignment is to extend the program discussed in class fortranslating Arithmetic expressions to IR code. The extension is toevaluate binary operators in a manner that decreases the number ofregisters needed. The rule of thumb is that given a binary operator(exp1 + exp2) we should first translate the sub expression (eitherexp1 or exp2) that is more demanding. I.e. we should translate firstthe sub expression that when translated will require the mostregisters.

See the assignments link on the class web page for a full description.