diff options
author | Vladimir Azarov <avm@intermediate-node.net> | 2025-08-09 01:17:24 +0200 |
---|---|---|
committer | Vladimir Azarov <avm@intermediate-node.net> | 2025-08-09 01:17:24 +0200 |
commit | 9bc877d781b988768c79d40a0f6a7055e9ad14e7 (patch) | |
tree | 72ea857d9df1a9dc179e82e1809220013a995606 /emit.fun | |
parent | ffee5da4dab26c8500add63da540ee252545370f (diff) |
Register map
Diffstat (limited to 'emit.fun')
-rw-r--r-- | emit.fun | 145 |
1 files changed, 115 insertions, 30 deletions
@@ -20,27 +20,27 @@ functor Emit(I: IL) = struct datatype affinity = AfHard of reg | AfSoft of int list | AfUnk val regs = [ - (Rax, 0), - (Rdx, 1), - (Rsp, 2), - (Rbp, 3), - - (Rcx, 4), - (Rsi, 5), - (Rdi, 6), - (R8, 7), - (R9, 8), - (R10, 9), - (R11, 10), - - (Rbx, 11), - (R12, 12), - (R13, 13), - (R14, 14), - (R15, 15) + (Rcx, 0), + (Rsi, 1), + (Rdi, 2), + (R8, 3), + (R9, 4), + (R10, 5), + (R11, 6), + + (Rbx, 7), + (R12, 8), + (R13, 9), + (R14, 10), + (R15, 11), + + (Rax, 12), + (Rdx, 13), + (Rsp, 14), + (Rbp, 15) ] - val firstUsedReg = 4 + val callerSavedRegs = 7 val usedRegNum = 12 fun reg2idx reg = @@ -512,7 +512,7 @@ functor Emit(I: IL) = struct fun returnToPool pool reg = let - val idx = reg2idx reg - firstUsedReg + val idx = reg2idx reg in Array.update (pool, idx, NONE) end @@ -577,7 +577,7 @@ functor Emit(I: IL) = struct | NONE => let val () = Array.update (pool, idx, SOME vr); - val reg = idx2reg (firstUsedReg + idx) + val reg = idx2reg idx val () = printfn R poff `"assigned (first) reg " Preg reg `" to %" ip vr % @@ -596,7 +596,7 @@ functor Emit(I: IL) = struct rev acc else case Array.sub (pool, idx) of - NONE => loop (idx + 1) (idx2reg (idx + firstUsedReg) :: acc) + NONE => loop (idx + 1) (idx2reg idx :: acc) | SOME _ => loop (idx + 1) acc in loop 0 [] @@ -658,7 +658,7 @@ functor Emit(I: IL) = struct let in updReg rinfo vr (VtReg reg); - Array.update (pool, reg2idx reg - firstUsedReg, SOME vr); + Array.update (pool, reg2idx reg, SOME vr); printfn R (poff + 1) `"assigned (by affinity) reg " Preg reg `" to %" ip vr %; printfn R (poff + 1) @@ -680,7 +680,7 @@ functor Emit(I: IL) = struct val () = printfn R poff `"trying to assign hard reg " A1 preg reg `" to %" ip vr % - val regIdx = reg2idx reg - firstUsedReg + val regIdx = reg2idx reg val user = Array.sub (pool, regIdx) fun setOurReg () = @@ -731,7 +731,7 @@ functor Emit(I: IL) = struct let val vr = #1 int - val regIdx = reg2idx reg - firstUsedReg + val regIdx = reg2idx reg val u = valOf $ Array.sub (pool, regIdx) val (uAff, _) = Array.sub (rinfo, u) @@ -789,7 +789,7 @@ functor Emit(I: IL) = struct val () = printfn `"spilling!!!" % in Array.update (pool, idx, SOME vr); - updReg rinfo vr (VtReg $ idx2reg (idx + firstUsedReg)); + updReg rinfo vr (VtReg $ idx2reg idx); putToStack 1 I (#1 spill); changeInActive active int (#1 spill) end @@ -859,7 +859,7 @@ functor Emit(I: IL) = struct val (_, vt) = Array.sub (rinfo, idx) in case vt of - VtReg reg => Array.update (regs, reg2idx reg - firstUsedReg, true) + VtReg reg => Array.update (regs, reg2idx reg, true) | _ => (); loop (idx + 1) end @@ -870,13 +870,95 @@ functor Emit(I: IL) = struct acc else if Array.sub (regs, idx) then - collect (idx + 1) (idx2reg (idx + firstUsedReg) :: acc) + collect (idx + 1) (idx2reg idx :: acc) else collect (idx + 1) acc in collect 0 [] end + fun getRegsToSave rinfo = + let + val regs = getUsedRegs rinfo + in + List.filter (fn r => reg2idx r >= callerSavedRegs) regs + end + + fun initMap len = + let + open Array + val map = array (len, array (callerSavedRegs, NONE)) + val i = ref 1 + in + while !i < len do ( + update (map, !i, array (callerSavedRegs, NONE)); + i := !i + 1 + ); + map + end + + fun computeMap len intervals rinfo = + let + val map = initMap len + + fun addInt (vr, startp, endp) = + case #2 $ Array.sub (rinfo, vr) of + VtReg reg => + let + fun f idx = + if reg2idx reg >= callerSavedRegs orelse idx = endp then + () + else + let + val row = Array.sub (map, idx) + in + Array.update (row, reg2idx reg, SOME vr); + f (idx + 1) + end + in + f (startp + 1) + end + | _ => () + in + List.app addInt intervals; + map + end + + fun printMap map = + let + val () = printfn `"Register map\n" % + + fun printHeader idx = + if idx = callerSavedRegs then + printf `"\n" % + else ( + printfp 5 `" " Preg (idx2reg idx) `" " %; + printHeader (idx + 1) + ) + + val () = printf `" " % + val () = printHeader 0 + + fun printRow (idx, row) = + let + val () = printf Ip 4 idx `": " % + + fun loop idx = + if idx = callerSavedRegs then + printf `"\n" % + else ( + case Array.sub (row, idx) of + NONE => printf `" " % + | SOME vr => printfp 5 `"%" I vr `" " %; + loop (idx + 1) + ) + in + loop 0 + end + in + Array.appi printRow map + end + fun regAlloc (F as I.Fi { vregs, ops, paramNum, ... }) = let val (toAlloc, regInfo) = prepareRegInfo paramNum ops vregs @@ -889,9 +971,12 @@ functor Emit(I: IL) = struct val () = linearscan regInfo intervals val () = printAlloced regInfo toAlloc - val usedRegs = getUsedRegs regInfo + val regsToSave = getRegsToSave regInfo val () = printfn - `"used registers: " Plist preg usedRegs (", ", true, 0) % + `"registers to save: " Plist preg regsToSave (", ", true, 0) % + + val regMap = computeMap (D.length ops) intervals regInfo + val () = printMap regMap in raise Unimplemented end |