|
@ -1,5 +1,5 @@ |
|
|
import { createGraph, Graph } from "./data/graph" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { colorGreedy, createGraph, Graph, maxCardinalitySearch } from "./data/graph" |
|
|
|
|
|
import { R8, StackOffset } from "./sm83/cpu" |
|
|
import type { Loc } from "./ir/loc" |
|
|
import type { Loc } from "./ir/loc" |
|
|
import type { SSA } from "./ir/ssa" |
|
|
import type { SSA } from "./ir/ssa" |
|
|
|
|
|
|
|
@ -39,10 +39,14 @@ export const locations = (block: Array): Set => { |
|
|
const ls: Set<Loc> = new Set() |
|
|
const ls: Set<Loc> = new Set() |
|
|
|
|
|
|
|
|
block.forEach(ssa => { |
|
|
block.forEach(ssa => { |
|
|
|
|
|
ls.add(ssa.dest) |
|
|
|
|
|
|
|
|
|
|
|
if (typeof ssa.source !== "number") { |
|
|
|
|
|
ls.add(ssa.source) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if ("source1" in ssa && typeof ssa.source1 !== "number") { |
|
|
if ("source1" in ssa && typeof ssa.source1 !== "number") { |
|
|
ls.add(ssa.source1) |
|
|
ls.add(ssa.source1) |
|
|
} else if (typeof ssa.source !== "number") { |
|
|
|
|
|
ls.add(ssa.source) |
|
|
|
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
@ -51,13 +55,53 @@ export const locations = (block: Array): Set => { |
|
|
|
|
|
|
|
|
export const interference = (block: Array<SSA>, live: LivenessInfo): Graph<Loc> => |
|
|
export const interference = (block: Array<SSA>, live: LivenessInfo): Graph<Loc> => |
|
|
createGraph((v, e) => { |
|
|
createGraph((v, e) => { |
|
|
|
|
|
const locs = locations(block) |
|
|
|
|
|
locs.forEach(loc => { |
|
|
|
|
|
v(loc.toString(), loc) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
block.forEach((ssa, i) => |
|
|
block.forEach((ssa, i) => |
|
|
live[i + 1].forEach(u => { |
|
|
live[i + 1].forEach(u => { |
|
|
if (ssa.dest.toString() !== u.toString()) { |
|
|
if (ssa.dest.toString() !== u.toString()) { |
|
|
v(ssa.dest.toString(), ssa.dest) |
|
|
|
|
|
v(u.toString(), u) |
|
|
|
|
|
e(ssa.dest.toString(), u.toString()) |
|
|
e(ssa.dest.toString(), u.toString()) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
) |
|
|
) |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
type RegAlloc = { |
|
|
|
|
|
[s: string]: R8 | StackOffset, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export const allocateRegisters = (block: Array<SSA>): RegAlloc => { |
|
|
|
|
|
const info = liveness(block) |
|
|
|
|
|
const graph = interference(block, info) |
|
|
|
|
|
const ordering = maxCardinalitySearch(graph) |
|
|
|
|
|
const coloring = colorGreedy(graph, ordering) |
|
|
|
|
|
|
|
|
|
|
|
const allocation: RegAlloc = {} |
|
|
|
|
|
const availableRegisters = new Set(Object.values(R8)) |
|
|
|
|
|
const colorMap: { [c: number]: R8 | StackOffset } = {} |
|
|
|
|
|
let nextStackOffset = 0 |
|
|
|
|
|
|
|
|
|
|
|
Object.entries(coloring.colors).forEach(([vertex, color]) => { |
|
|
|
|
|
if (typeof colorMap[color] !== 'undefined') { |
|
|
|
|
|
allocation[vertex] = colorMap[color] |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let value = null |
|
|
|
|
|
if (availableRegisters.size == 0) { |
|
|
|
|
|
value = { offset: nextStackOffset++ } |
|
|
|
|
|
} else { |
|
|
|
|
|
const result = availableRegisters.values().next() |
|
|
|
|
|
value = result.value |
|
|
|
|
|
availableRegisters.delete(value) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
allocation[vertex] = value |
|
|
|
|
|
colorMap[color] = value |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
return allocation |
|
|
|
|
|
} |