180 likes | 350 Views
CPSC 388 – Compiler Design and Construction. More Code Generation. Register Code. Some architectures support opcodes for direct manipulation of the stack with expressions Add (takes top two values of stack and adds them, placing result on stack)
E N D
CPSC 388 – Compiler Design and Construction More Code Generation
Register Code • Some architectures support opcodes for direct manipulation of the stack with expressions • Add (takes top two values of stack and adds them, placing result on stack) • For architectures with registers using the stack is suboptimal #pop value of e1 into t1 addu $sp, $sp, 4 lw $t1, 0($sp) # pop value of e0 into t0 addu $sp, $sp, 4 lw $t0, 0($sp) # do the subtraction sub $t0, $t0, $t1 # push the result sw $t0, 0($sp) subu $sp,$sp,4
How to Optimize Register Usage? • Clean up stack-based code like previous, removing redundant pushes and pops • Directly utilize registers • Replace codeGen() with codeGen(int k) which generates value of exp and leaves it in register $sk
Example Binary Expression codeGen(int k) • myExp1.codeGen(k); • myExp2.codeGen(k+1); • Generate: op-code $sk, $sk, $sk+1
Additional Worries • Procedure prolgue must save all registers used by the procedure • Procedure calls can be more efficient by passing values in registers • What happens when you run out of registers? • Insert “spill” code that temporarily copies values from registers to stack and then later restores them from the stack • Sethi-Ullman register allocation algorithm determines how many registers are needed for an expression and which sub-expressions will need to spill
Sethi-Ullman Algorithm • Phase 1 • Label each node in expression tree with the number of registers needed to evaluate that node without any spills • Phase 2 • Given a list of available registers, generate code to evaluate expression, leaving value in register. If num registers enough then no spills, otherwise code includes smallest number of spills
Assumptions • All operators are binary • No short-circuited operators • Every instruction is of the form: • opcode dest, src1, src2 • 3 possibilities for operands • Both in registers • 1st in register, 2nd in memory • 1st in register, 2nd a literal
Phase 1 • Visit nodes bottom-up • For a leaf node: If left child of parent then label=1 Else label = 0 • For non-leaf node t, with left child label j and right child label k If j==k then label(t)=j+1 Else label(t)=max(j,k) • Why the number of registers?
Example Expression • (a*b) + ((a-c) + (d*e)) • Create Tree and perform Phase 1
Phase 2 – generate code • Recursively use genCode with params: • N: a tree node • regList: a list of available registers • Tmp: the index of the next temporary • Call genCode: • N=root node of tree • regList=list of all registers • Tmp=1 • Each call to genCode returns the register that holds the subtree expression’s value • Sometimes right subexpression evaluated first, but that’s okay as long operation performed correctly, e.g. (a+b) / (c+d)
Phase 2: case 1 //left leaf for var/literal X R = first(regList) Gen(“load R, x”) Return R
Phase 2: Case 2 // right child is leaf R=genCode(n1,regList,tmp) Gen(“op R, R, x”) Return R op n1 X:0
Phase 2: Case 3 – K <=J and K>0 and K < length(regList) R0 = genCode(n1, regList, tmp) R1 = genCode(n2, regList-R0, tmp) Gen(“op R0, R0, R1”) Return R0 op n1:j n2:k
Phase 2: Case 3 – J < K and J < length(regList) Similar to case 2, but do n2 first op n1:j n2:k
Phase 2: Case 3 – both j and k >= length(regList) R = genCode(n2, regList, tmp) Gen(“store R TMP<tmp>”) R = genCode(n1, regList, tmp+1) Gen(“op R, R, TMP<tmp>”) Return R op n1:j n2:k
Example (a*b) + ((a-c)+(d*e)) • Example 1: (no spills) initial regList=(T0,T1) • Result code: Load T0, a - T0, T0, c Load T1, T1, e * T1, T1, e + T0, T0, T1 Load T1, a * T1, T1, b + T1, T1, T0
Example (with spills) • Initial regList = {T0} • Resulting code: Load T0, d * T0, T0, e Store T0, TMP1 Load T0, a - T0, T0, c + T0, T0, TMP1 Store T0, TMP1 Load T0, a * T0, T0, b + T0, T0, TMP1
You Try It • How many registers needed for each expression if evaluated left-to-right? If evaluted using Sethi-Ullman? • ((a+b)+c)+d • a+(b+(c+d) • What is the smallest expression that requires 5 registers if you don’t use Sethi-Ullman? What is the smallest expression that requires 5 registers with Sethi-Ullman?