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

instruction selection for tiger
SMART_READER_LITE
LIVE PREVIEW

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


slide-1
SLIDE 1

Compilation 2015

Instruction Selection for Tiger

Aslan Askarov aslan@cs.au.dk
 
 
 Based on slides by E. Ernst

slide-2
SLIDE 2

Instruction Selection for Tiger

  • The algorithms, e.g., Maximal Munch, did not show

which registers were used to carry results

  • Ex: typical memory access ➜
  • We must handle:
  • choice of registers
  • consistency across tiling
  • explicit representation


(needed during static analysis)

+ CONST e c MEM EBX

FP

slide-3
SLIDE 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
slide-4
SLIDE 4

Abstract Assembly for Tiger

  • New module ‘Assem’
  • Instructions datatype:
  • allows arbitrary syntax


in assem: a string

  • assem actually has structure: 


backquote marks “parameters”

  • `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

datatype instr = OPER of { assem:string , dst: temp list , src: temp list , jump: label list

  • ption}

| LABEL of { assem: string , lab: label} | MOVE of { assem: string , dst: temp , src: temp}

slide-5
SLIDE 5

Example Instr

  • A single tile IR tree:
  • Corresponding instr:
  • Note:
  • dst/src/jump index selects list element
  • jump NONE means fall through

OPER { assem = "LOAD `d0 <- M[`s0+8]" , dst = [Temp.newtemp()] , src = [Frame.FP] , jump = NONE}

MEM + TEMP FP CONST 8

slide-6
SLIDE 6

Example Instr

  • A multi tile IR tree:
  • Corresponding instrs:
  • Note: t908, t909, t910 fresh, t910 returned

assem dst src "ADDI `d0 <- `s0+3" t908 t87 "LOAD `d0 <- M[`s0+0]" t909 t92 "MUL `d0 <- `s0*`s1" t910 t908,t909

* + TEMP t87 CONST 3 MEM TEMP t92

slide-7
SLIDE 7

Two-address Instructions

  • CISC format, think "+=" etc.
  • Corresponding instr:
  • Notation similar to Jouette:
  • Realistic assembly syntax:

assem dst src "ADD `d0,`s1" t1 t1,t2

MOVE + TEMP t1 TEMP t2 TEMP t1

ADD t1 ⃪ t1 + t2 ADD t1,t2

slide-8
SLIDE 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}) ...

slide-9
SLIDE 9

Maximal Munch

  • Note that CALL case involves “artificial” src/dest
  • munchArgs returns registers used during call;


depends on parameter passing mechanism (arguments, static link, frame pointer, …)

  • 0 is argument number of hd args

... | munchStm (EXP(CALL(e,args))) = emit (A.OPER{ assem = "CALL `s0\n" , src = munchExp e :: munchArgs (0,args) , dst = calldefs , jump = NONE} ...

slide-10
SLIDE 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

slide-11
SLIDE 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-effects

slide-12
SLIDE 12

Be Careful…

  • Note that some instructions affect 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

slide-13
SLIDE 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

slide-14
SLIDE 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

slide-15
SLIDE 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
slide-16
SLIDE 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