Commit 451d4887 authored by qinsoon's avatar qinsoon

[wip] spill1 works fine. Need to test correctness of calling

convention(stack args), and need to optimize spill1 code
parent 01b35984
......@@ -386,7 +386,7 @@ impl MachineCode for ASMCode {
}
}
fn replace_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize) {
fn replace_define_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize) {
let to_reg_string : MuName = match backend::all_regs().get(&to) {
Some(ref machine_reg) => {
let name = machine_reg.name().unwrap();
......@@ -408,8 +408,20 @@ impl MachineCode for ASMCode {
// remove old key, insert new one
asm.defines.remove(&from);
asm.defines.insert(from, define_locs);
asm.defines.insert(to, define_locs);
}
}
fn replace_use_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize) {
let to_reg_string : MuName = match backend::all_regs().get(&to) {
Some(ref machine_reg) => {
let name = machine_reg.name().unwrap();
"%".to_string() + &name
},
None => REG_PLACEHOLDER.clone()
};
let asm = &mut self.code[inst];
// if this reg is used, replace the use
if asm.uses.contains_key(&from) {
......@@ -423,7 +435,7 @@ impl MachineCode for ASMCode {
// remove old key, insert new one
asm.uses.remove(&from);
asm.uses.insert(from, use_locs);
asm.uses.insert(to, use_locs);
}
}
......@@ -1802,18 +1814,22 @@ pub fn spill_rewrite(
// iterate through all instructions
for i in 0..cf.mc().number_of_insts() {
trace!("---Inst {}---", i);
// find use of any register that gets spilled
{
let reg_uses = cf.mc().get_inst_reg_uses(i).to_vec();
for reg in reg_uses {
if spills.contains_key(&reg) {
let val_reg = func.context.get_value(reg).unwrap().value().clone();
// a register used here is spilled
let spill_mem = spills.get(&reg).unwrap();
// generate a random new temporary
let temp_ty = func.context.get_value(reg).unwrap().ty().clone();
let temp_ty = val_reg.ty.clone();
let temp = func.new_ssa(vm.next_id(), temp_ty).clone_value();
vec_utils::add_unique(&mut new_nodes, temp.clone());
trace!("reg {} used in Inst{} is replaced as {}", val_reg, i, temp);
// generate a load
let code = {
......@@ -1832,7 +1848,7 @@ pub fn spill_rewrite(
}
// replace register reg with temp
cf.mc_mut().replace_tmp_for_inst(reg, temp.id(), i);
cf.mc_mut().replace_use_tmp_for_inst(reg, temp.id(), i);
}
}
}
......@@ -1842,11 +1858,14 @@ pub fn spill_rewrite(
let reg_defines = cf.mc().get_inst_reg_defines(i).to_vec();
for reg in reg_defines {
if spills.contains_key(&reg) {
let val_reg = func.context.get_value(reg).unwrap().value().clone();
let spill_mem = spills.get(&reg).unwrap();
let temp_ty = func.context.get_value(reg).unwrap().ty().clone();
let temp_ty = val_reg.ty.clone();
let temp = func.new_ssa(vm.next_id(), temp_ty).clone_value();
vec_utils::add_unique(&mut new_nodes, temp.clone());
trace!("reg {} defined in Inst{} is replaced as {}", val_reg, i, temp);
let code = {
let mut codegen = ASMCodeGen::new();
......@@ -1863,7 +1882,7 @@ pub fn spill_rewrite(
spill_code_after.insert(i, vec![code]);
}
cf.mc_mut().replace_tmp_for_inst(reg, temp.id(), i);
cf.mc_mut().replace_define_tmp_for_inst(reg, temp.id(), i);
}
}
}
......
......@@ -50,6 +50,7 @@ pub struct GraphColoring<'a> {
impl <'a> GraphColoring<'a> {
pub fn start (func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> Result<GraphColoring<'a>, RegAllocFailure> {
trace!("Initializing coloring allocator...");
cf.mc().trace_mc();
let ig = graph_coloring::build_inteference_graph(cf, func);
......@@ -109,8 +110,6 @@ impl <'a> GraphColoring<'a> {
}
fn regalloc(mut self) -> Result<GraphColoring<'a>, RegAllocFailure> {
trace!("Initializing coloring allocator...");
trace!("---InterenceGraph---");
self.ig.print(&self.func.context);
......@@ -646,30 +645,6 @@ impl <'a> GraphColoring<'a> {
}
let new_temps = backend::spill_rewrite(&spilled_mem, self.func, self.cf, self.vm);
//
// self.spilled_nodes.clear();
//
// self.initial = {
// let mut ret = vec![];
//
// for node in self.colored_nodes.iter() {
// vec_utils::add_unique(&mut ret, node.clone());
// }
// for node in self.coalesced_nodes.iter() {
// vec_utils::add_unique(&mut ret, node.clone());
// }
//
// // create nodes for every new temp
// for tmp in new_temps {
// let node = self.ig.new_node(tmp.id(), &func.context);
// vec_utils::add_unique(&mut ret, node.clone());
// }
//
// ret
// };
//
// self.colored_nodes.clear();
// self.coalesced_nodes.clear();
}
pub fn spills(&self) -> Vec<MuID> {
......
......@@ -321,15 +321,11 @@ fn build_live_set(cf: &mut CompiledFunction, func: &MuFunctionVersion) {
}
for block in cf.mc().get_all_blocks().to_vec() {
if cf.mc().get_ir_block_livein(&block).is_none() {
let start_inst = cf.mc().get_block_range(&block).unwrap().start;
cf.mc_mut().set_ir_block_livein(&block, livein[start_inst].to_vec());
}
if cf.mc().get_ir_block_liveout(&block).is_none() {
let end_inst = cf.mc().get_block_range(&block).unwrap().end;
cf.mc_mut().set_ir_block_liveout(&block, liveout[end_inst].to_vec());
}
let start_inst = cf.mc().get_block_range(&block).unwrap().start;
cf.mc_mut().set_ir_block_livein(&block, livein[start_inst].to_vec());
let end_inst = cf.mc().get_block_range(&block).unwrap().end;
cf.mc_mut().set_ir_block_liveout(&block, liveout[end_inst].to_vec());
}
}
......
......@@ -123,7 +123,8 @@ pub trait MachineCode {
/// replace a temp with a machine register (to_reg must be a machine register)
fn replace_reg(&mut self, from: MuID, to: MuID);
/// replace a temp with another temp
fn replace_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
fn replace_define_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
fn replace_use_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
fn set_inst_nop(&mut self, index: usize);
fn as_any(&self) -> &Any;
......
......@@ -74,111 +74,6 @@ fn test_ir_liveness_fac() {
assert!(vec_utils::is_identical_to_str_ignore_order(block_2_liveout, expect));
}
use mu::compiler::backend::reg_alloc::graph_coloring::GraphColoring;
use mu::compiler::backend::reg_alloc::graph_coloring::InterferenceGraph;
use mu::compiler::backend::init_machine_regs_for_func;
use std::any::Any;
struct InspectInterferenceGraph {
name: &'static str,
ig: Option<InterferenceGraph>,
}
impl InspectInterferenceGraph {
pub fn new() -> InspectInterferenceGraph {
InspectInterferenceGraph {
name: "Inspect Interference Graph",
ig: None
}
}
}
impl CompilerPass for InspectInterferenceGraph {
fn name(&self) -> &'static str {
self.name
}
fn as_any(&self) -> &Any {
self
}
fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> PassExecutionResult {
debug!("---CompilerPass {} for {}---", self.name(), func);
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
// initialize machine registers for the function context
init_machine_regs_for_func(&mut func.context);
let coloring = match GraphColoring::start(func, &mut cf, vm) {
Ok(coloring) => coloring,
Err(_) => panic!("error during coloring - unexpected")
};
self.ig = Some(coloring.ig);
PassExecutionResult::ProceedToNext
}
}
#[test]
#[allow(unused_variables)]
fn test_spill1_ig() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm = Arc::new(create_spill1());
let compiler = Compiler::new(CompilerPolicy::new({
let mut passes : Vec<Box<CompilerPass>> = vec![];
passes.push(Box::new(passes::DefUse::new()));
passes.push(Box::new(passes::TreeGen::new()));
passes.push(Box::new(passes::ControlFlowAnalysis::new()));
passes.push(Box::new(passes::TraceGen::new()));
// compilation
passes.push(Box::new(backend::inst_sel::InstructionSelection::new()));
passes.push(Box::new(InspectInterferenceGraph::new()));
passes
}), vm.clone());
let func_id = vm.id_of("spill1");
{
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_id).unwrap().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
let compiler_policy = compiler.get_policy().borrow();
let inspect_ig : &InspectInterferenceGraph = compiler_policy.passes[5].as_any().downcast_ref().unwrap();
let ig = inspect_ig.ig.as_ref().unwrap();
let t1 = ig.get_node(vm.id_of("blk_entry_t1"));
let t2 = ig.get_node(vm.id_of("blk_entry_t2"));
let t3 = ig.get_node(vm.id_of("blk_entry_t3"));
let t4 = ig.get_node(vm.id_of("blk_entry_t4"));
let t5 = ig.get_node(vm.id_of("blk_entry_t5"));
let t6 = ig.get_node(vm.id_of("blk_entry_t6"));
let t7 = ig.get_node(vm.id_of("blk_entry_t7"));
let t8 = ig.get_node(vm.id_of("blk_entry_t8"));
let t9 = ig.get_node(vm.id_of("blk_entry_t9"));
let t10= ig.get_node(vm.id_of("blk_entry_t10"));
let res0 = ig.get_node(vm.id_of("blk_entry_res0"));
let res1 = ig.get_node(vm.id_of("blk_entry_res1"));
let res2 = ig.get_node(vm.id_of("blk_entry_res2"));
let res3 = ig.get_node(vm.id_of("blk_entry_res3"));
// t1 interferes with t2
assert!(ig.is_interferenced_with(t1, t2));
}
#[test]
#[allow(unused_variables)]
fn test_spill1() {
......@@ -208,6 +103,8 @@ fn test_spill1() {
Ok(symbol) => symbol,
Err(e) => panic!("cannot find symbol spill1 in dylib: {:?}", e)
};
// we cannot call this (it doesnt return)
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment