WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.3% of users enabled 2FA.

Commit 69e8132a authored by qinsoon's avatar qinsoon
Browse files

[wip] simple_spill works

parent a6b8e16b
......@@ -94,6 +94,19 @@ impl <'a> GraphColoring<'a> {
coloring.regalloc()
}
fn display_node(&self, node: Node) -> String {
let id = self.ig.get_temp_of(node);
self.display_id(id)
}
fn display_id(&self, id: MuID) -> String {
self.func.context.get_temp_display(id)
}
fn display_move(&self, m: Move) -> String {
format!("Move: {} -> {}", self.display_node(m.from), self.display_node(m.to))
}
fn regalloc(mut self) -> Result<GraphColoring<'a>, RegAllocFailure> {
trace!("Initializing coloring allocator...");
......@@ -121,10 +134,7 @@ impl <'a> GraphColoring<'a> {
let outdegree = self.ig.outdegree_of(node);
self.degree.insert(node, outdegree);
trace!("{} has a degree of {}", {
let id = self.ig.get_temp_of(node);
self.func.context.get_temp_display(id)
}, outdegree);
trace!("{} has a degree of {}", self.display_node(node), outdegree);
}
}
......@@ -155,7 +165,7 @@ impl <'a> GraphColoring<'a> {
if cfg!(debug_assertions) {
trace!("nodes to be spilled:");
for node in self.spilled_nodes.iter() {
trace!("{:?}: {:?}", node, self.ig.get_temp_of(*node));
trace!("{}", self.display_node(*node));
}
}
......@@ -173,7 +183,7 @@ impl <'a> GraphColoring<'a> {
let ref ig = self.ig;
let ref mut movelist = self.movelist;
for m in ig.moves() {
trace!("add {:?} to movelist", m);
trace!("add to movelist: {:?}", m);
self.worklist_moves.push(m.clone());
GraphColoring::movelist_mut(movelist, m.from).borrow_mut().push(m.clone());
GraphColoring::movelist_mut(movelist, m.to).borrow_mut().push(m.clone());
......@@ -195,13 +205,13 @@ impl <'a> GraphColoring<'a> {
degree >= n_regs
} {
trace!("{} 's degree >= reg number limit (K), push to spill list", self.node_info(node));
trace!("{} 's degree >= reg number limit (K), push to spill list", self.display_node(node));
self.worklist_spill.push(node);
} else if self.is_move_related(node) {
trace!("{} is move related, push to freeze list", self.node_info(node));
trace!("{} is move related, push to freeze list", self.display_node(node));
self.worklist_freeze.insert(node);
} else {
trace!("{} has small degree and not move related, push to simplify list", self.node_info(node));
trace!("{} has small degree and not move related, push to simplify list", self.display_node(node));
self.worklist_simplify.insert(node);
}
}
......@@ -262,7 +272,7 @@ impl <'a> GraphColoring<'a> {
// remove next element from worklist_simplify, we know its not empty
let node = self.worklist_simplify.pop_front().unwrap();
trace!("Simplifying {}", self.node_info(node));
trace!("Simplifying {}", self.display_node(node));
self.select_stack.push(node);
......@@ -304,14 +314,14 @@ impl <'a> GraphColoring<'a> {
return;
}
trace!("decrement degree of {}", self.node_info(n));
trace!("decrement degree of {}", self.display_node(n));
let d = self.degree(n);
debug_assert!(d != 0);
self.degree.insert(n, d - 1);
if d == self.n_regs_for_node(n) {
trace!("{}'s degree is K, no longer need to spill it", self.node_info(n));
trace!("{}'s degree is K, no longer need to spill it", self.display_node(n));
let mut nodes = self.adjacent(n);
nodes.insert(n);
trace!("enable moves of {:?}", nodes);
......@@ -320,10 +330,10 @@ impl <'a> GraphColoring<'a> {
vec_utils::remove_value(&mut self.worklist_spill, n);
if self.is_move_related(n) {
trace!("{} is move related, push to freeze list", self.node_info(n));
trace!("{} is move related, push to freeze list", self.display_node(n));
self.worklist_freeze.insert(n);
} else {
trace!("{} is not move related, push to simplify list", self.node_info(n));
trace!("{} is not move related, push to simplify list", self.display_node(n));
self.worklist_simplify.insert(n);
}
}
......@@ -345,11 +355,11 @@ impl <'a> GraphColoring<'a> {
fn coalesce(&mut self) {
let m = self.worklist_moves.pop().unwrap();
trace!("Coalescing on {}", self.move_info(m));
trace!("Coalescing on {}", self.display_move(m));
let x = self.get_alias(m.from);
let y = self.get_alias(m.to);
trace!("resolve alias: from {} to {}", self.node_info(x), self.node_info(y));
trace!("resolve alias: from {} to {}", self.display_node(x), self.display_node(y));
let (u, v, precolored_u, precolored_v) = {
if self.precolored.contains(&y) {
......@@ -369,8 +379,8 @@ impl <'a> GraphColoring<'a> {
}
};
trace!("u={}, v={}, precolored_u={}, precolroed_v={}",
self.node_info(u),
self.node_info(v),
self.display_node(u),
self.display_node(v),
precolored_u, precolored_v);
if u == v {
......@@ -511,7 +521,7 @@ impl <'a> GraphColoring<'a> {
fn freeze(&mut self) {
// it is not empty (checked before)
let node = self.worklist_freeze.pop_front().unwrap();
trace!("Freezing {}...", self.node_info(node));
trace!("Freezing {}...", self.display_node(node));
self.worklist_simplify.insert(node);
self.freeze_moves(node);
......@@ -567,7 +577,7 @@ impl <'a> GraphColoring<'a> {
// m is not none
let m = m.unwrap();
trace!("Spilling {}...", self.node_info(m));
trace!("Spilling {}...", self.display_node(m));
vec_utils::remove_value(&mut self.worklist_spill, m);
self.worklist_simplify.insert(m);
......@@ -578,7 +588,7 @@ impl <'a> GraphColoring<'a> {
trace!("---coloring done---");
while !self.select_stack.is_empty() {
let n = self.select_stack.pop().unwrap();
trace!("Assigning color to {}", self.node_info(n));
trace!("Assigning color to {}", self.display_node(n));
let mut ok_colors : LinkedHashSet<MuID> = self.colors.get(&self.ig.get_group_of(n)).unwrap().clone();
for w in self.ig.outedges_of(n) {
......@@ -591,11 +601,11 @@ impl <'a> GraphColoring<'a> {
trace!("available colors: {:?}", ok_colors);
if ok_colors.is_empty() {
trace!("{} is a spilled node", self.node_info(n));
trace!("{} is a spilled node", self.display_node(n));
self.spilled_nodes.push(n);
} else {
let first_available_color = ok_colors.pop_front().unwrap();
trace!("Color {} as {}", self.node_info(n), first_available_color);
trace!("Color {} as {}", self.display_node(n), first_available_color);
if !backend::is_callee_saved(first_available_color) {
warn!("Use caller saved register {}", first_available_color);
......@@ -606,13 +616,13 @@ impl <'a> GraphColoring<'a> {
}
}
for n in self.coalesced_nodes.iter() {
for n in self.colored_nodes.iter() {
let n = *n;
let alias = self.get_alias(n);
let alias_color = self.ig.get_color_of(alias).unwrap();
trace!("Assign color to {} based on aliased {}", self.node_info(n), self.node_info(alias));
trace!("Color {} as {}", self.node_info(n), alias_color);
trace!("Assign color to {} based on aliased {}", self.display_node(n), self.display_node(alias));
trace!("Color {} as {}", self.display_node(n), alias_color);
self.ig.color_node(n, alias_color);
}
......@@ -674,13 +684,4 @@ impl <'a> GraphColoring<'a> {
spills
}
fn node_info(&self, node: Node) -> String {
let reg = self.ig.get_temp_of(node);
format!("{:?}/Reg {}", node, reg)
}
fn move_info(&self, m: Move) -> String {
format!("Move: {} -> {}", self.node_info(m.from), self.node_info(m.to))
}
}
......@@ -3,6 +3,7 @@ extern crate log;
extern crate simple_logger;
extern crate libloading;
use aot;
use test_ir::test_ir::factorial;
use self::mu::compiler::*;
use self::mu::utils::vec_utils;
......@@ -362,5 +363,297 @@ fn create_spill1() -> VM {
vm.define_func_version(func_ver);
vm
}
#[test]
fn test_simple_spill() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm = Arc::new(create_simple_spill());
let compiler = Compiler::new(CompilerPolicy::default(), vm.clone());
let func_id = vm.id_of("simple_spill");
{
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);
}
backend::emit_context(&vm);
let dylib = aot::link_dylib(vec![Mu("simple_spill")], "libsimple_spill.dylib");
let lib = libloading::Library::new(dylib.as_os_str()).unwrap();
unsafe {
let simple_spill : libloading::Symbol<unsafe extern fn() -> u64> = match lib.get(b"simple_spill") {
Ok(symbol) => symbol,
Err(e) => panic!("cannot find symbol simple_spill in dylib: {:?}", e)
};
let res = simple_spill();
println!("simple_spill() = {}", res);
assert!(res == 2);
}
}
fn create_simple_spill() -> VM {
let vm = VM::new();
// .typedef @int_64 = int<64>
let type_def_int64 = vm.declare_type(vm.next_id(), MuType_::int(64));
vm.set_name(type_def_int64.as_entity(), Mu("int_64"));
// .const @int_64_1 <@int_64> = 1
let const_def_int64_1 = vm.declare_const(vm.next_id(), type_def_int64.clone(), Constant::Int(1));
vm.set_name(const_def_int64_1.as_entity(), "int64_1".to_string());
// .funcsig @simple_spill_sig = () -> (@int_64)
let simple_spill_sig = vm.declare_func_sig(vm.next_id(), vec![type_def_int64.clone()], vec![]);
vm.set_name(simple_spill_sig.as_entity(), Mu("simple_spill_sig"));
// .funcdecl @simple_spill <@simple_spill_sig>
let func = MuFunction::new(vm.next_id(), simple_spill_sig.clone());
vm.set_name(func.as_entity(), Mu("simple_spill"));
let func_id = func.id();
vm.declare_func(func);
// .funcdef @simple_spill VERSION @simple_spill_v1 <@simple_spill_sig>
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, simple_spill_sig.clone());
vm.set_name(func_ver.as_entity(), Mu("simple_spill_v1"));
// %entry():
let mut blk_entry = Block::new(vm.next_id());
vm.set_name(blk_entry.as_entity(), Mu("entry"));
// BRANCH %start(1, 1, 1, 1, ..., 1) // 14 constant ONE
let const_int64_1 = func_ver.new_constant(const_def_int64_1.clone());
let blk_start_id = vm.next_id();
let blk_entry_branch = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![const_int64_1.clone(); 14]),
v: Instruction_::Branch1(Destination{
target: blk_start_id,
args: vec![
DestArg::Normal(0),
DestArg::Normal(1),
DestArg::Normal(2),
DestArg::Normal(3),
DestArg::Normal(4),
DestArg::Normal(5),
DestArg::Normal(6),
DestArg::Normal(7),
DestArg::Normal(8),
DestArg::Normal(9),
DestArg::Normal(10),
DestArg::Normal(11),
DestArg::Normal(12),
DestArg::Normal(13),
]
})
});
blk_entry.content = Some(BlockContent {
args: vec![],
exn_arg: None,
body: vec![blk_entry_branch],
keepalives: None
});
// %start(%t1, %t2, ..., %t14):
let mut blk_start = Block::new(blk_start_id);
vm.set_name(blk_start.as_entity(), Mu("start"));
// args
let blk_start_t1 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t1.as_entity(), Mu("blk_start_t1"));
let blk_start_t2 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t2.as_entity(), Mu("blk_start_t2"));
let blk_start_t3 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t3.as_entity(), Mu("blk_start_t3"));
let blk_start_t4 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t4.as_entity(), Mu("blk_start_t4"));
let blk_start_t5 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t5.as_entity(), Mu("blk_start_t5"));
let blk_start_t6 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t6.as_entity(), Mu("blk_start_t6"));
let blk_start_t7 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t7.as_entity(), Mu("blk_start_t7"));
let blk_start_t8 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t8.as_entity(), Mu("blk_start_t8"));
let blk_start_t9 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t9.as_entity(), Mu("blk_start_t9"));
let blk_start_t10= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t10.as_entity(), Mu("blk_start_t10"));
let blk_start_t11= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t11.as_entity(), Mu("blk_start_t11"));
let blk_start_t12= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t12.as_entity(), Mu("blk_start_t12"));
let blk_start_t13= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t13.as_entity(), Mu("blk_start_t13"));
let blk_start_t14= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_t14.as_entity(), Mu("blk_start_t14"));
// %res = ADD %t1 %t2
let blk_start_res = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_start_res.as_entity(), Mu("blk_start_res"));
let blk_start_add = func_ver.new_inst(Instruction {
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![blk_start_res.clone_value()]),
ops: RwLock::new(vec![blk_start_t1.clone(), blk_start_t2.clone()]),
v: Instruction_::BinOp(BinOp::Add, 0, 1)
});
// BRANCH %ret (%res, %t1, %t2, ..., %t14)
let blk_ret_id = vm.next_id();
let blk_start_branch = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![
blk_start_res.clone(),
blk_start_t1.clone(),
blk_start_t2.clone(),
blk_start_t3.clone(),
blk_start_t4.clone(),
blk_start_t5.clone(),
blk_start_t6.clone(),
blk_start_t7.clone(),
blk_start_t8.clone(),
blk_start_t9.clone(),
blk_start_t10.clone(),
blk_start_t11.clone(),
blk_start_t12.clone(),
blk_start_t13.clone(),
blk_start_t14.clone(),
]),
v: Instruction_::Branch1(Destination{
target: blk_ret_id,
args: vec![
DestArg::Normal(0),
DestArg::Normal(1),
DestArg::Normal(2),
DestArg::Normal(3),
DestArg::Normal(4),
DestArg::Normal(5),
DestArg::Normal(6),
DestArg::Normal(7),
DestArg::Normal(8),
DestArg::Normal(9),
DestArg::Normal(10),
DestArg::Normal(11),
DestArg::Normal(12),
DestArg::Normal(13),
DestArg::Normal(14),
]
})
});
blk_start.content = Some(BlockContent {
args: vec![
blk_start_t1.clone_value(),
blk_start_t2.clone_value(),
blk_start_t3.clone_value(),
blk_start_t4.clone_value(),
blk_start_t5.clone_value(),
blk_start_t6.clone_value(),
blk_start_t7.clone_value(),
blk_start_t8.clone_value(),
blk_start_t9.clone_value(),
blk_start_t10.clone_value(),
blk_start_t11.clone_value(),
blk_start_t12.clone_value(),
blk_start_t13.clone_value(),
blk_start_t14.clone_value(),
],
exn_arg: None,
body: vec![blk_start_add, blk_start_branch],
keepalives: None
});
// %ret(%res, %t1, %t2, ... %t14):
let mut blk_ret = Block::new(blk_ret_id);
vm.set_name(blk_ret.as_entity(), Mu("ret"));
// args
let blk_ret_res = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_res.as_entity(), Mu("blk_ret_res"));
let blk_ret_t1 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t1.as_entity(), Mu("blk_ret_t1"));
let blk_ret_t2 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t2.as_entity(), Mu("blk_ret_t2"));
let blk_ret_t3 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t3.as_entity(), Mu("blk_ret_t3"));
let blk_ret_t4 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t4.as_entity(), Mu("blk_ret_t4"));
let blk_ret_t5 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t5.as_entity(), Mu("blk_ret_t5"));
let blk_ret_t6 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t6.as_entity(), Mu("blk_ret_t6"));
let blk_ret_t7 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t7.as_entity(), Mu("blk_ret_t7"));
let blk_ret_t8 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t8.as_entity(), Mu("blk_ret_t8"));
let blk_ret_t9 = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t9.as_entity(), Mu("blk_ret_t9"));
let blk_ret_t10= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t10.as_entity(), Mu("blk_ret_t10"));
let blk_ret_t11= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t11.as_entity(), Mu("blk_ret_t11"));
let blk_ret_t12= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t12.as_entity(), Mu("blk_ret_t12"));
let blk_ret_t13= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t13.as_entity(), Mu("blk_ret_t13"));
let blk_ret_t14= func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_ret_t14.as_entity(), Mu("blk_ret_t14"));
// RET %res
let blk_ret_ret = func_ver.new_inst(Instruction {
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![blk_ret_res.clone()]),
v: Instruction_::Return(vec![0])
});
blk_ret.content = Some(BlockContent {
args: vec![
blk_ret_res.clone_value(),
blk_ret_t1.clone_value(),
blk_ret_t2.clone_value(),
blk_ret_t3.clone_value(),
blk_ret_t4.clone_value(),
blk_ret_t5.clone_value(),
blk_ret_t6.clone_value(),
blk_ret_t7.clone_value(),
blk_ret_t8.clone_value(),
blk_ret_t9.clone_value(),
blk_ret_t10.clone_value(),
blk_ret_t11.clone_value(),
blk_ret_t12.clone_value(),
blk_ret_t13.clone_value(),
blk_ret_t14.clone_value(),
],
exn_arg: None,
body: vec![blk_ret_ret],
keepalives: None
});
func_ver.define(FunctionContent {
entry: blk_entry.id(),
blocks: {
let mut blocks = HashMap::new();
blocks.insert(blk_entry.id(), blk_entry);
blocks.insert(blk_start.id(), blk_start);
blocks.insert(blk_ret.id(), blk_ret);
blocks
}
});
vm.define_func_version(func_ver);
vm
}
\ No newline at end of file
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