instruction selection for tiger
play

Instruction Selection for Tiger Aslan Askarov aslan@cs.au.dk Based - PowerPoint PPT Presentation

Compilation 2015 Instruction Selection for Tiger Aslan Askarov aslan@cs.au.dk Based on slides by E. Ernst Instruction Selection for Tiger The algorithms, e.g., Maximal Munch, did not show which registers were used to carry


  1. 
 
 Compilation 2015 Instruction Selection for Tiger Aslan Askarov aslan@cs.au.dk 
 Based on slides by E. Ernst

  2. Instruction Selection for Tiger • The algorithms, e.g., Maximal Munch, did not show which registers were used to carry results MEM EBX • Ex: typical memory access ➜ + • We must handle: e CONST FP • choice of registers c • consistency across tiling • explicit representation 
 (needed during static analysis)

  3. Register Allocation Timing • Register allocation: Choosing concrete registers for assembly instructions • Possible timing: • before tiling (imprecise!! – don’t even know tile roots) • during tiling (not impossible – somewhat imprecise) • after tiling (most powerful model; portable, too) • Requires abstract assembly instructions: • very flexible representation of actual assembly code • generic, externally accessible representation of temps • encoding both explicit and implicit usage

  4. Abstract Assembly for Tiger datatype instr = • New module ‘Assem’ OPER of { assem:string , dst: temp list • Instructions datatype: , src: temp list • allows arbitrary syntax 
 , jump: label list option} in assem : a string | LABEL of { assem: string , lab: label} • assem actually has structure: 
 | MOVE of { assem: string backquote marks “parameters” , dst: temp , src: temp} • `si `di `ji marks 
 source number i , destination i , jump i , in fields src , dst , jump ( NONE : fall through, SOME _ : all targets) • MOVE just a special case of OPER : analyzable! • Independent of CPU, registers

  5. Example Instr • A single tile IR tree: MEM + TEMP FP CONST 8 • Corresponding instr : OPER { assem = "LOAD `d0 <- M[`s0+8]" , dst = [Temp.newtemp()] , src = [Frame.FP] , jump = NONE} • Note: • dst/src/jump index selects list element • jump NONE means fall through

  6. Example Instr • A multi tile IR tree: * MEM + TEMP t92 • Corresponding instr s: TEMP t87 CONST 3 assem dst src "ADDI `d0 <- `s0+3" t908 t87 "LOAD `d0 <- M[`s0+0]" t909 t92 "MUL `d0 <- `s0*`s1" t910 t908,t909 • Note: t908, t909, t910 fresh, t910 returned

  7. Two-address Instructions • CISC format, think "+=" etc. MOVE + TEMP t1 TEMP t1 TEMP t2 • Corresponding instr : assem dst src "ADD `d0,`s1" t1 t1,t2 • Notation similar to Jouette: ADD t1 ⃪ t1 + t2 • Realistic assembly syntax: ADD t1,t2

  8. Maximal Munch • Register aware Maximal Munch algorithm, 
 munchStm: Tree.stm -> unit fun munchStm (SEQ(a,b)) = (munchStm a; munchStm b) | munchStm (MOVE(MEM(BINOP(PLUS,e1,CONST i)),e2)) = emit (A.OPER{ assem = "STORE M[`s0+" ^ int i ^ "] <- `s1\n" , src = [munchExp e1, munchExp e2] , dst = [], jump = NONE} | munchStm (MOVE(MEM(BINOP(PLUS,CONST i,e1)),e2)) = emit (A.OPER{ assem = "STORE M[`s0+" ^ int i ^ "] <- `s1\n" , src = [munchExp e1, munchExp e2] , dst = [], jump = NONE} | munchStm (MOVE(MEM e1,MEM e2)) = emit (A.OPER{ assem = "MOVE M[`s0] <- M[`s1]\n" , src = [munchExp e1, munchExp e2] , dst = [], jump = NONE} ... | munchStm (LABEL lab) = emit (A.LABEL {assem = lab ^ ":\n", lab = lab}) ...

  9. Maximal Munch • Note that CALL case involves “artificial” src/dest ... | munchStm (EXP(CALL(e,args))) = emit (A.OPER{ assem = "CALL `s0\n" , src = munchExp e :: munchArgs (0,args) , dst = calldefs , jump = NONE} ... • munchArgs returns registers used during call; 
 depends on parameter passing mechanism (arguments, static link, frame pointer, …) • 0 is argument number of hd args

  10. Maximal Munch • munchExp: Tree.stm -> Temp.temp and munchExp (MEM(BINOP(PLUS,e1,CONST i))) = result (fn r => emit (A.OPER { assem = "LOAD `d0 <- M[`s0+" ^ int i ^ "]\n" , src = [munchExp e1], dst = [r], jump = NONE} | munchExp (MEM(BINOP(PLUS,CONST i,e1))) = result (fn r => emit (A.OPER { assem = "LOAD `d0 <- M[`s0+" ^ int i ^ "]\n" , src = [munchExp e1], dst = [r], jump = NONE} | munchExp (MEM(CONST i)) = result (fn r => emit (A.OPER { assem = "LOAD `d0 <- M[r0+" ^ int i ^ "]\n" , src = [munchExp e1], dst = [r], jump = NONE} ... | munchExp (BINOP(PLUS,e1,e2)) = result (fn r => emit (A.OPER { assem = "ADD `d0 <-`s0+`s1\n" , src = [munchExp e1, munchExp e2] , dst = [r], jump = NONE} | munchExp (TEMP t) = t Note the use of result

  11. Maximal Munch • codegen: frame -> stm -> instr list fun codegen frame (stm: Tree.stm): Assem.instr list = let val ilist = ref (nil: instr list) fun emit x = (ilist := x::ilist) fun result gen = let val t = newtemp() in gen t; t end fun munchStm ... fun munchExp ... in munchStm stm; rev (!ilist) end Note definition of result and use of side-e ff ects

  12. Be Careful… • Note that some instructions a ff ect registers not mentioned explicitly (!) ... | munchExp (BINOP(MUL,e1,e2)) = result (fn r => ... emit (A.OPER{ assem = "IMUL `s1" , src = [F.EAX, r] , dst = [F.EAX, F.EDX] , jump = NONE}) ... High bits used for 32*32->64 bit computation, rarely Common view: it “trashes” EDX

  13. Be Careful… • Tempting approach to handling returned value ... emit (A.OPER { assem = "CALL " ^S.name lab^ "\n" (* result: EAX *) , src = munchArgs args , dst = F.calldefs , jump = NONE}); emit (... (* clean up stack *)); emit (A.OPER { assem = "STORE M[`s0+0] <- `s1\n" , src = [munchExp e1, F.EAX] (* overwrite EAX! *) , dst = [] , jump = NONE}) ... Problem: generated code destroys fixed register

  14. Being Careful… • Working approach to handle returned value ... val t = newtemp() ... emit (A.OPER { assem = "CALL " ^S.name lab^ "\n" (* result: EAX *) , src = munchArgs args , dst = F.calldefs , jump = NONE}); emit (... (* clean up stack *)); emit (A.MOVE { assem = "MOVE `d0 <- `s0\n" (* result: t *) , src = F.EAX , dst = t}); emit (A.OPER { assem = "STORE M[`s0+0] <- `s1\n" , src = [munchExp e1, t] (* no overwrite *) , dst = [] , jump = NONE}) ... Trick: fresh temp protects value

  15. Whither Frame Pointer? • Fixed size activation record possible • must consider entire body: all function calls • no alloca(…) • Frame pointer then derived: FP ≡ SP+c • Omitting frame pointer saves one register at zero cost • Historically, this is the trend

  16. Summary • Instruction selection algorithms omitted registers • Needs abstract assembly (flexible location spec) • Module Assem: OPER/LABEL/MOVE • `s0, `d1, `j2, matching src/dst/jump • Register aware Maximal Munch (Stm,Exp) • MUL trashes EDX ; overwriting CALL/EAX/t • Frame pointer may be omitted

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend