///|
pub fn Module::alloc_register(self : Module) -> Unit raise MIRError {
for func in self.functions.values() {
func.alloc_register()
}
}
///|
pub fn Function::alloc_register(self : Function) -> Unit raise MIRError {
// Step 1. Liveness Analysis
self.live_analysis()
//if self.name == "analyze_float_bits" {
// println("============== After liveness analysis ==============")
// println(self)
//}
// Step 2. Build the interference graph.
let interf_graph = self.build_interference_graph()
// Step 2. Build the Preference List
let pref_list = self.build_preference_list()
// Step 3. Graph Coloring, get a replacement map
let (replacement_map, spilled_count) = interf_graph.coloring(pref_list)
if spilled_count != self.spilled_count {
let extra_spilled = spilled_count - self.spilled_count
let _ = self.extend_reg_stack(extra_spilled.to_int64() * 8, 8L)
}
let need_rewrite = !replacement_map.is_empty() ||
spilled_count != self.spilled_count
// Step 4. If replacement map is not empty:
// rewrite the function, legalize, then back to Step 1,
// otherwise we're done.
if need_rewrite {
self.rewrite_by_replacement_map(replacement_map)
self.legalize()
self.alloc_register()
}
}
//
// This Will clear live in and live out.
///|
pub fn Function::rewrite_by_replacement_map(
self : Function,
replacement_map : Map[Operand, Operand],
) -> Unit {
self.body.each(bb => bb.rewrite_by_replacement_map(replacement_map))
}
// This Will clear live in and live out.
///|
pub fn BasicBlock::rewrite_by_replacement_map(
self : BasicBlock,
replacement_map : Map[Operand, Operand],
) -> Unit {
self.insts.each(inst => inst.rewrite_by_replacement_map(replacement_map))
self.live_in.clear()
self.live_out.clear()
}
// This Will clear live in and live out.
///|
pub fn Instruction::rewrite_by_replacement_map(
self : Instruction,
replacement_map : Map[Operand, Operand],
) -> Unit {
for i, def in self.defs {
match def {
Mem(base, offset) =>
// Check if the base register needs replacement
if replacement_map.get(IRegister(base)) is Some(IRegister(new_base)) {
self.defs[i] = Mem(new_base, offset)
}
_ => if replacement_map.get(def) is Some(repl) { self.defs[i] = repl }
}
}
for i, use_ in self.uses {
match use_ {
Mem(base, offset) =>
// Check if the base register needs replacement
if replacement_map.get(IRegister(base)) is Some(IRegister(new_base)) {
self.uses[i] = Mem(new_base, offset)
}
_ => if replacement_map.get(use_) is Some(repl) { self.uses[i] = repl }
}
}
self.live_in.clear()
self.live_out.clear()
}