Commit 5d318fee authored by qinsoon's avatar qinsoon Committed by Isaac Oscar Gariano

we should not coalesce a temporary with an unusable regsiter

parent 856903b6
Pipeline #940 failed with stages
in 4 minutes and 43 seconds
......@@ -273,6 +273,16 @@ impl MuFunctionVersion {
})
}
pub fn new_machine_reg(&mut self, v: P<Value>) -> P<TreeNode> {
self.context
.values
.insert(v.id(), SSAVarEntry::new(v.clone()));
P(TreeNode {
v: TreeNode_::Value(v)
})
}
pub fn new_constant(&mut self, v: P<Value>) -> P<TreeNode> {
P(TreeNode {
v: TreeNode_::Value(v)
......
......@@ -493,7 +493,7 @@ impl<'a> GraphColoring<'a> {
// if they are not from the same register group, we cannot coalesce them
if self.ig.get_group_of(m.from) != self.ig.get_group_of(m.to) {
info!("a move instruction of two temporaries of different reigsters group");
info!("a move instruction of two temporaries of different register groups");
info!("from: {:?}, to: {:?}", m.from, m.to);
return;
......@@ -532,6 +532,22 @@ impl<'a> GraphColoring<'a> {
precolored_v
);
// if u or v is a machine register that is not usable/not a color, we cannot coalesce
if self.precolored.contains(&u) {
let reg_u = self.ig.get_temp_of(u);
let group = backend::pick_group_for_reg(reg_u);
if !self.colors.get(&group).unwrap().contains(&reg_u) {
return;
}
}
if self.precolored.contains(&v) {
let reg_v = self.ig.get_temp_of(v);
let group = backend::pick_group_for_reg(reg_v);
if !self.colors.get(&group).unwrap().contains(&reg_v) {
return;
}
}
if u == v {
trace!("u == v, coalesce the move");
self.coalesced_moves.insert(m);
......
......@@ -192,6 +192,12 @@ macro_rules! ssa {
}
}
macro_rules! machine_reg {
(($vm: expr, $fv: ident) $name: ident = $mreg: expr) => {
let $name = $fv.new_machine_reg($mreg.clone());
}
}
macro_rules! consta {
(($vm: expr, $fv: ident) $name: ident = $c: ident) => {
let $name = $fv.new_constant($c.clone());
......
......@@ -18,6 +18,7 @@ extern crate libloading;
use mu::linkutils;
use mu::linkutils::aot;
use mu::utils::LinkedHashMap;
use mu::compiler::backend::x86_64;
use test_compiler::test_call::gen_ccall_exit;
use self::mu::compiler::*;
use self::mu::ast::ir::*;
......@@ -2038,3 +2039,74 @@ fn spill_int8() -> VM {
vm
}
#[test]
#[cfg(target_arch = "x86_64")]
fn test_coalesce_unusable_reg() {
VM::start_logging_trace();
let vm = coalesce_unusable_reg();
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
let func_id = vm.id_of("coalesce_unusable_reg");
{
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 compiled_funcs = vm.compiled_funcs().read().unwrap();
let cf_lock = compiled_funcs.get(&func_ver.id()).unwrap();
let cf = cf_lock.read().unwrap();
let x_id = vm.id_of("x");
// x exists
assert!(cf.temps.contains_key(&x_id));
// x is not rsp
let x_color = *cf.temps.get(&x_id).unwrap();
println!("x is assigned to {}", x_color);
assert!(x_color != x86_64::RSP.id());
}
}
#[cfg(target_arch = "x86_64")]
fn coalesce_unusable_reg() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
funcsig! ((vm) sig = () -> (int64));
funcdecl! ((vm) <sig> coalesce_unusable_reg);
funcdef! ((vm) <sig> coalesce_unusable_reg VERSION coalesce_unusable_reg_v1);
block! ((vm, coalesce_unusable_reg_v1) blk_entry);
ssa! ((vm, coalesce_unusable_reg_v1) <int64> x);
machine_reg!((vm, coalesce_unusable_reg_v1) rsp = x86_64::RSP);
inst! ((vm, coalesce_unusable_reg_v1) blk_entry_mov:
MOVE rsp -> x
);
inst! ((vm, coalesce_unusable_reg_v1) blk_entry_ret:
RET (x)
);
define_block!((vm, coalesce_unusable_reg_v1) blk_entry() {
blk_entry_mov,
blk_entry_ret
});
define_func_ver!((vm) coalesce_unusable_reg_v1 (entry: blk_entry) {
blk_entry
});
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