1 / 18

CPSC 388 – Compiler Design and Construction

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)

lenci
Télécharger la présentation

CPSC 388 – Compiler Design and Construction

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CPSC 388 – Compiler Design and Construction More Code Generation

  2. 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

  3. 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

  4. Example Binary Expression codeGen(int k) • myExp1.codeGen(k); • myExp2.codeGen(k+1); • Generate: op-code $sk, $sk, $sk+1

  5. 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

  6. 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

  7. 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

  8. 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?

  9. Example Expression • (a*b) + ((a-c) + (d*e)) • Create Tree and perform Phase 1

  10. 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)

  11. Phase 2: case 1 //left leaf for var/literal X R = first(regList) Gen(“load R, x”) Return R

  12. Phase 2: Case 2 // right child is leaf R=genCode(n1,regList,tmp) Gen(“op R, R, x”) Return R op n1 X:0

  13. 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

  14. Phase 2: Case 3 – J < K and J < length(regList) Similar to case 2, but do n2 first op n1:j n2:k

  15. 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

  16. 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

  17. 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

  18. 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?

More Related