1.08k likes | 1.09k Views
Code Generation. The target machine Instruction selection and register allocation Basic blocks and flow graphs A simple code generator Peephole optimization Instruction selector generator Graph-coloring register allocator. The Target Machine.
E N D
Code Generation • The target machine • Instruction selection and register allocation • Basic blocks and flow graphs • A simple code generator • Peephole optimization • Instruction selector generator • Graph-coloring register allocator
The Target Machine • A byte addressable machine with four bytes to a word and n general purpose registers • Two address instructions • opsource, destination • Six addressing modes • absolute M M 1 • register R R 0 • indexed c(R) c+content(R) 1 • ind register *R content(R) 0 • ind indexed *c(R) content(c+content(R)) 1 • literal #c c 1
Examples MOV R0, M MOV 4 (R0), M MOV *R0, M MOV *4 (R0), M MOV #1, R0
Instruction Costs • Cost of an instruction = 1 + costs of source and destination addressing modes • This cost corresponds to the length (in words) of the instruction • Minimize instruction length also tend to minimize the instruction execution time
Examples MOV R0, R1 1 MOV R0, M 2 MOV #1, R0 2 MOV 4 (R0), *12 (R1) 3
An Example Consider a := b + c 1. MOV b, R0 2. MOV b, a ADD c, R0 ADD c, a MOV R0, a 3. R0, R1, R2 contains 4. R1, R2 contains the addresses of a, b, c the values of b, c MOV *R1, *R0 ADD R2, R1 ADD *R2, *R0 MOV R1, a
Instruction Selection • Code skeleton x := y + z a := b + c d := a + e MOV y, R0 MOV b, R0 MOV a, R0 ADD z, R0 ADD c, R0 ADD e, R0 MOV R0, x MOV R0, a MOV R0, d • Multiple choices a := a + 1 MOV a, R0 INC a ADD #1, R0 MOV R0, a
Register Allocation • Register allocation: select the set of variables that will reside in registers • Register assignment: pick the specific register that a variable will reside in • The problem is NP-complete
An Example t := a + b t := a + b t := t * c t := t + c t := t / d t := t / d MOV a, R1 MOV a, R0 ADD b, R1 ADD b, R0 MUL c, R0 ADD c, R0 DIV d, R0 SRDA R0, 32 MOV R1, t DIV d, R0 MOV R1, t
Basic Blocks • A basic block is a sequence of consecutive statements in which control enters at the beginning and leaves at the end without halt or possibility of branching except at the end
An Example (1) prod := 0 (2) i := 1 (3) t1 := 4 * i (4) t2 := a[t1] (5) t3 := 4 * i (6) t4 := b[t3] (7) t5 := t2 * t4 (8) t6 := prod + t5 (9) prod := t6 (10) t7 := i + 1 (11) i := t7 (12) if i <= 20 goto (3)
Flow Graphs • A flow graph is a directed graph • The nodes in the graph are basic blocks • There is an edge from B1 to B2 iff B2 immediately follows B1 in some execution sequence • B2 immediately follows B1 in program text • there is a jump from B1 to B2 • B1 is a predecessor of B2, B2 is a successor of B1
An Example (1) prod := 0 (2) i := 1 (3) t1 := 4 * i (4) t2 := a[t1] (5) t3 := 4 * i (6) t4 := b[t3] (7) t5 := t2 * t4 (8) t6 := prod + t5 (9) prod := t6 (10) t7 := i + 1 (11) i := t7 (12) if i <= 20 goto (3) B0 B1
Construction of Basic Blocks • Determine the set of leaders • the first statement is a leader • the target of a jump is a leader • any statement immediately following a jump is a leader • For each leader, its basic block consists of the leader and all statements up to but not including the next leader or the end of the program
Representation of Basic Blocks • Each basic block is represented by a record consisting of • a count of the number of statements • a pointer to the leader • a list of predecessors • a list of successors
Define and Use • A three address statement x := y + z is said to define x and to use y and z • A name is live in a basic block at a given point if its value is used after that point, perhaps in another basic block
Next-Use Information i: x := … … no assignment to x j: y := … x … Statement juses the value of x defined at i
An Example b:(1), c:(1,4), d:(2) (1) a := b + c a:(2,3,5), c:(4), d:(2) (2) e := a + d a:(3,5), c:(4), e:(3) (3) f := e - a a:(5), c:(4), f:(4) (4) e := f + c a:(5), e:(5) (5) g := e - a g:(?) b, c, d are live at the beginning of the block
Computing Next Uses • Scan statements “i: x := y op z” backward • Attach to statement ithe information currently found in the symbol table regarding the next uses and liveness of x, y, and z • In the symbol table, set x to “not live” and clear the next uses” of x • In the symbol table, set y and z to “live” and add i to the “next uses” of y and z among blocks within blocks
A Simple Code Generator • Consider each statement in a basic block in turn, remembering if operands are in registers • Assume that • each operator has a corresponding target language operator • computed results can be left in registers as long as possible, unless • out of registers • at the end of a basic block
Register and Address Descriptors • A register descriptor keeps track of what is currently in each register • An address descriptor keeps track of the location(s) where the current value of the name can be found at run time
An Example d := (a - b) + (a - c) + (a - c) [ ] [ ] t := a - b MOV a, R0 [R0:(t)] SUB b, R0 [t:(R0)] u := a - c MOV a, R1 [R0:(t), R1:(u)] SUB c, R1 [t:(R0), u:(R1)] v := t + u ADD R1, R0 [R0:(v), R1:(u)] [v:(R0), u:(R1)] d := v + u ADD R1, R0 [R0:(d)] [d:(R0)] MOV R0, d [ ] [ ]
Code Generation Algorithm • Consider an instruction of the form “x := y op z” • Invoke getreg to determine the location L where the result of “y op z” will be placed • Determine a current location y’ of y from the address descriptor (register location preferred). If y’ is notL, generate “MOV y’, L” • Generate “opz’, L”, where z’ is a current location of z from the address descriptor. • Update the address and register descriptors for x, y, z, and L
Code Generation Algorithm • Consider an instruction of the form “x := y” • If y is in a register, change the register and address descriptors • If y is in memory, • if x has next use in the block, invoke getreg to find a registerr, generate “MOV y, r”, and makerthe location of x • otherwise, generate “MOV y, x”
Code Generation Algorithm • Once all statements in the basic block are processed, we store those names that are liveon exit and not in their memory locations
The Function getreg • Consider an instruction of the form “x := y op z” • If y is in a register r that holds the value of no other names, and y is not live and no next uses after this statement, return r • Otherwise, return an emptyregisterr if there is one • Otherwise, if x has a next use in the block, or op is an operator requiring a register, find an occupied registerr. Store the value of r, update address descriptor, and return r • If x has no next use, or no suitable occupied register can be found, return the memory location of x
An Example d := (a - b) + (a - c) + (a - c) [ ] [ ] t := a - b MOV a, R0 [R0:(t)] SUB b, R0 [t:(R0)] u := a - c MOV a, R1 [R0:(t), R1:(u)] SUB c, R1 [t:(R0), u:(R1)] v := t + u ADD R1, R0 [R0:(v), R1:(u)] [v:(R0), u:(R1)] d := v + u ADD R1, R0 [R0:(d)] [d:(R0)] MOV R0, d [ ] [ ]
Indexing and Pointer Operations i in Ri i in Mi i in Si(A) a := b[i] MOV b(Ri), R MOV Mi, R MOV Si(A), R MOV b(R), R MOV b(R), R a[i] := b MOV b, a(Ri) MOV Mi, R MOV Si(A), R MOV b, a(R) MOV b, a(R) p in Rp p in Mp p in Sp(A) a := *p MOV *Rp, R MOV Mp, R MOV Sp(A), R MOV *R, R MOV *R, R *p := a MOV a, *Rp MOV Mp, R Mov a, R MOV a, *R MOV R, *Sp(A)
Conditional Statements • Condition codes if x < y goto z CMP x, y CJ< z • Conditon code descriptors x := y + z MOV y, R0 if x < 0 goto z ADD z, R0 MOV R0, x CJ< z
Global Register Allocation • Keep live variables in registers across block boundaries • Keep variables frequently used in inner loops in registers
Loops • A loop is a collection of nodes such that • all nodes in the collection are strongly connected • the collection of nodes has a unique entry • An inner loop is one that contains no other loops
Variable Usage Counts • Savings • Count a saving of one for each use of x in loop L that is not preceded by an assignment to x in the same block • Save two units if we can avoid a store of x at the end of a block • Costs • Cost two units if x is live at the entry or exit of the inner loop
b,c,d,f a := b + c d := d - b e := a + f B1 a,c,d,f a,c,d,e a,c,d,e,f b := d + f e := a - c B2 B3 f := a - d c,d,e,f c,d,e,f b,d,e,f b,c,d,e,f B4 b := d + c b,c,d,e,f b,c,d,e,f An Example
An Example use(a, B1) = 0, use(a, B2) = 1 use(a, B3) = 1, use(a, B4) = 0 live(a, B1) = 1, live(a, B2) = 0 live(a, B3) = 0, live(a, B4) = 0 save(a) = (0+1+1+0) + 2 (1+0+0+0) = 4 save(b) = 5 save(c) = 3 save(d) = 6 save(e) = 4 save(f) = 4
MOV b, R1; MOV d, R2 MOV R1, R0; ADD c, Ro SUB R1, R2; MOV R0, R3 ADD f, R3; MOV R3, e B1 B2 B3 MOV R0, R3; SUB R2, R3 MOV R3, f MOV R2, R1; ADD f, R1 MOV R0, R1; SUB c, R3 MOV R3, e B4 MOV R2, R1; ADD c, R1 MOV R1, b; MOV R2, d MOV R1, b; MOV R2, d An Example
Register Assignment for Outer Loops • Apply the same idea for inner loops to progressively larger loops • If an outer loop L1 contains an inner loop L2, a name allocated a register in L2 need not be allocated a register in L1-L2 • If name x is allocated a register in L1 but not L2, need store x on entrance to L2 and load x on exit from L2 • If name x is allocated a register in L2 but not L1, need load x on entrance to L2 and store x on exit from L2
Peephole Optimization • Improve the performance of the target program by examining and transforming a short sequence of target instructions • May need repeated passes over the code • Can also be applied directly after intermediate code generation
Examples • Redundant loads and storesMOV R0, a MOV a, Ro • Algebraic Simplificationx := x + 0 x := x * 1 • Constant foldingx := 2 + 3 x := 5 y := x + 3 y := 8
Examples • Unreachable code#define debug 0 if (debug) (print debugging information) if 0 <> 1 goto L1 print debugging informationL1: if 1 goto L1 print debugging informationL1:
Examples • Flow-of-control optimization goto L1 goto L2 … …L1: goto L2 L2: goto L2 goto L1 if a < b goto L2 … goto L3L1: if a < b goto L2 …L3: L3:
Examples • Reduction in strength: replace expensive operations by cheaper ones • x2 x * x • fixed-point multiplication and division by a power of 2 shift • floating-point division by a constant floating-point multiplication by a constant
Examples • Use of machine Idioms: hardware instructions for certain specific operations • auto-increment and auto-decrement addressing mode (push or pop stack in parameter passing)
DAG Representation of Blocks • Easy to determine: • common subexpressions • names used in the block but evaluatedoutside the block • names whose values could be used outside the block
DAG Representation of Blocks • Leaves labeled by unique identifiers • Interior nodes labeled by operator symbols • Nodes optionally given a sequence of identifiers, having the value represented by the nodes
t6, prod t5 prod0 + + t4 t2 (1) [] [] <= t1,t3 a b 20 * * t7, i 4 i0 1 An Example (1) t1 := 4 * i (2) t2 := a[t1] (3) t3 := 4 * i (4) t4 := b[t3] (5) t5 := t2 * t4 (6) t6 := prod + t5 (7) prod := t6 (8) t7 := i + 1 (9) i := t7 (10) if i <= 20 goto (1)
Constructing a DAG • Consider x := y op z. Other statements can be handled similarly • If node(y) is undefined, create a leaf labeled y and let node(y) be this leaf. If node(z) is undefined, create a leaf labeled z and let node(z) be that leaf
Constructing a DAG • Determine if there is a node labeled op, whose left child is node(y) and its right child is node(z). If not, create such a node. Let n be the node found or created. • Delete x from the list of attached identifiers for node(x). Append x to the list of attached identifiers for the node n and set node(x) to n
Reconstructing Quadruples • Evaluate the interior nodes in topological order • Assign the evaluated value to one of its attached identifier x, preferring one whose value is needed outside the block • If there is no attached identifier, create a new temp to hold the value • If there are additional attached identifiers y1, y2, …, yk whose values are also needed outside the block, addy1 := x, y2 := x, …, yk := x
+ + [] [] <= * * An Example prod (1) t1 := 4 * i (2) t2 := a[t1] (3) t3 := b[t1] (4) t4 := t2 * t3 (5) prod := prod + t4 (6) i := i + 1 (7) if i <= 20 goto (1) prod0 (1) i a b 20 4 i0 1
Arrays, Pointers, Procedure Calls x := a[i] x := a[i] a[j] := y z := x z := a[i] a[j] := y => range analysis *p := w => aliasing analysis side effects caused by procedure calls => inter-procedural analysis