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.2% of users enabled 2FA.

Commit 6bfe400a authored by John Zhang's avatar John Zhang
Browse files

merge rpy-time

parents 4b949713 751795b1
......@@ -15,6 +15,7 @@ use utils::vec_utils;
use utils::string_utils;
use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
use std::collections::HashMap;
use std::str;
......@@ -778,13 +779,14 @@ impl ASMCodeGen {
fn add_asm_call(&mut self, code: String) {
// a call instruction will use all the argument registers
// do not need
let mut uses : HashMap<MuID, Vec<ASMLocation>> = HashMap::new();
for reg in x86_64::ARGUMENT_GPRs.iter() {
uses.insert(reg.id(), vec![]);
}
for reg in x86_64::ARGUMENT_FPRs.iter() {
uses.insert(reg.id(), vec![]);
}
// for reg in x86_64::ARGUMENT_GPRs.iter() {
// uses.insert(reg.id(), vec![]);
// }
// for reg in x86_64::ARGUMENT_FPRs.iter() {
// uses.insert(reg.id(), vec![]);
// }
// defines: return registers
let mut defines : HashMap<MuID, Vec<ASMLocation>> = HashMap::new();
......@@ -2822,14 +2824,23 @@ pub fn spill_rewrite(
vm: &VM) -> Vec<P<Value>>
{
trace!("spill rewrite for x86_64 asm backend");
trace!("code before spilling");
cf.mc().trace_mc();
let mut new_nodes = vec![];
// record code and their insertion point, so we can do the copy/insertion all at once
let mut spill_code_before: HashMap<usize, Vec<Box<ASMCode>>> = HashMap::new();
let mut spill_code_after: HashMap<usize, Vec<Box<ASMCode>>> = HashMap::new();
// map from old to new
let mut temp_for_cur_inst : HashMap<MuID, P<Value>> = HashMap::new();
// iterate through all instructions
for i in 0..cf.mc().number_of_insts() {
temp_for_cur_inst.clear();
trace!("---Inst {}---", i);
// find use of any register that gets spilled
{
......@@ -2843,7 +2854,7 @@ pub fn spill_rewrite(
// generate a random new temporary
let temp_ty = val_reg.ty.clone();
let temp = func.new_ssa(vm.next_id(), temp_ty).clone_value();
let temp = func.new_ssa(vm.next_id(), temp_ty.clone()).clone_value();
vec_utils::add_unique(&mut new_nodes, temp.clone());
trace!("reg {} used in Inst{} is replaced as {}", val_reg, i, temp);
......@@ -2851,7 +2862,12 @@ pub fn spill_rewrite(
let code = {
let mut codegen = ASMCodeGen::new();
codegen.start_code_sequence();
codegen.emit_mov_r_mem(&temp, spill_mem);
if is_fp(&temp_ty) {
codegen.emit_movsd_f64_mem64(&temp, spill_mem);
} else {
codegen.emit_mov_r_mem(&temp, spill_mem);
}
codegen.finish_code_sequence_asm()
};
......@@ -2865,6 +2881,8 @@ pub fn spill_rewrite(
// replace register reg with temp
cf.mc_mut().replace_use_tmp_for_inst(reg, temp.id(), i);
temp_for_cur_inst.insert(reg, temp.clone());
}
}
}
......@@ -2878,15 +2896,26 @@ pub fn spill_rewrite(
let spill_mem = spills.get(&reg).unwrap();
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());
let temp = if temp_for_cur_inst.contains_key(&reg) {
temp_for_cur_inst.get(&reg).unwrap().clone()
} else {
let temp_ty = val_reg.ty.clone();
let temp = func.new_ssa(vm.next_id(), temp_ty.clone()).clone_value();
vec_utils::add_unique(&mut new_nodes, temp.clone());
temp
};
trace!("reg {} defined in Inst{} is replaced as {}", val_reg, i, temp);
let code = {
let mut codegen = ASMCodeGen::new();
codegen.start_code_sequence();
codegen.emit_mov_mem_r(spill_mem, &temp);
if is_fp(&temp.ty) {
codegen.emit_movsd_mem64_f64(spill_mem, &temp);
} else {
codegen.emit_mov_mem_r(spill_mem, &temp);
}
codegen.finish_code_sequence_asm()
};
......@@ -2914,5 +2943,9 @@ pub fn spill_rewrite(
cf.mc = Some(new_mc);
trace!("spill rewrite done");
trace!("code after spilling");
cf.mc().trace_mc();
new_nodes
}
\ No newline at end of file
......@@ -229,6 +229,8 @@ impl <'a> InstructionSelection {
},
Instruction_::Select{cond, true_val, false_val} => {
use ast::op::CmpOp::*;
trace!("instsel on SELECT");
let ops = inst.ops.read().unwrap();
......@@ -239,59 +241,103 @@ impl <'a> InstructionSelection {
if self.match_ireg(true_val) {
// moving integers/pointers
let tmp_res = self.get_result_value(node);
let tmp_true = self.emit_ireg(true_val, f_content, f_context, vm);
let tmp_false = self.emit_ireg(false_val, f_content, f_context, vm);
// mov tmp_false -> tmp_res
self.backend.emit_mov_r_r(&tmp_res, &tmp_false);
if self.match_cmp_res(cond) {
match self.emit_cmp_res(cond, f_content, f_context, vm) {
op::CmpOp::EQ => {
self.backend.emit_cmove_r_r (&tmp_res, &tmp_true);
}
op::CmpOp::NE => {
self.backend.emit_cmovne_r_r(&tmp_res, &tmp_true);
}
op::CmpOp::SGE => {
self.backend.emit_cmovge_r_r(&tmp_res, &tmp_true);
}
op::CmpOp::SGT => {
self.backend.emit_cmovg_r_r (&tmp_res, &tmp_true);
}
op::CmpOp::SLE => {
self.backend.emit_cmovle_r_r(&tmp_res, &tmp_true);
}
op::CmpOp::SLT => {
self.backend.emit_cmovl_r_r (&tmp_res, &tmp_true);
}
op::CmpOp::UGE => {
self.backend.emit_cmovae_r_r(&tmp_res, &tmp_true);
}
op::CmpOp::UGT => {
self.backend.emit_cmova_r_r (&tmp_res, &tmp_true);
}
op::CmpOp::ULE => {
self.backend.emit_cmovbe_r_r(&tmp_res, &tmp_true);
}
op::CmpOp::ULT => {
self.backend.emit_cmovb_r_r (&tmp_res, &tmp_true);
}
_ => panic!("expecting CmpOp for integers")
}
// generate compare
let cmpop = if self.match_cmp_res(cond) {
self.emit_cmp_res(cond, f_content, f_context, vm)
} else if self.match_ireg(cond) {
let tmp_cond = self.emit_ireg(cond, f_content, f_context, vm);
// emit: mov tmp_false -> tmp_res
self.backend.emit_mov_r_r(&tmp_res, &tmp_false);
// emit: cmp cond_reg 1
self.backend.emit_cmp_imm_r(1, &tmp_cond);
// emit: cmove tmp_true -> tmp_res
self.backend.emit_cmove_r_r(&tmp_res, &tmp_true);
EQ
} else {
unimplemented!()
panic!("expected ireg, found {}", cond)
};
// use cmov for 16/32/64bit integeer
// use jcc for 8 bit
match tmp_res.ty.get_int_length() {
// cmov
Some(len) if len > 8 => {
let tmp_true = self.emit_ireg(true_val, f_content, f_context, vm);
let tmp_false = self.emit_ireg(false_val, f_content, f_context, vm);
// mov tmp_false -> tmp_res
self.backend.emit_mov_r_r(&tmp_res, &tmp_false);
match cmpop {
EQ => self.backend.emit_cmove_r_r (&tmp_res, &tmp_true),
NE => self.backend.emit_cmovne_r_r(&tmp_res, &tmp_true),
SGE => self.backend.emit_cmovge_r_r(&tmp_res, &tmp_true),
SGT => self.backend.emit_cmovg_r_r (&tmp_res, &tmp_true),
SLE => self.backend.emit_cmovle_r_r(&tmp_res, &tmp_true),
SLT => self.backend.emit_cmovl_r_r (&tmp_res, &tmp_true),
UGE => self.backend.emit_cmovae_r_r(&tmp_res, &tmp_true),
UGT => self.backend.emit_cmova_r_r (&tmp_res, &tmp_true),
ULE => self.backend.emit_cmovbe_r_r(&tmp_res, &tmp_true),
ULT => self.backend.emit_cmovb_r_r (&tmp_res, &tmp_true),
FOEQ | FUEQ => self.backend.emit_cmove_r_r (&tmp_res, &tmp_true),
FONE | FUNE => self.backend.emit_cmovne_r_r(&tmp_res, &tmp_true),
FOGT | FUGT => self.backend.emit_cmova_r_r (&tmp_res, &tmp_true),
FOGE | FUGE => self.backend.emit_cmovae_r_r(&tmp_res, &tmp_true),
FOLT | FULT => self.backend.emit_cmovb_r_r (&tmp_res, &tmp_true),
FOLE | FULE => self.backend.emit_cmovbe_r_r(&tmp_res, &tmp_true),
_ => unimplemented!()
}
}
// jcc
_ => {
let blk_true = format!("{}_select_true", node.id());
let blk_end = format!("{}_select_end", node.id());
// jump to blk_true if true
match cmpop {
EQ => self.backend.emit_je (blk_true.clone()),
NE => self.backend.emit_jne(blk_true.clone()),
SGE => self.backend.emit_jge(blk_true.clone()),
SGT => self.backend.emit_jg (blk_true.clone()),
SLE => self.backend.emit_jle(blk_true.clone()),
SLT => self.backend.emit_jl (blk_true.clone()),
UGE => self.backend.emit_jae(blk_true.clone()),
UGT => self.backend.emit_ja (blk_true.clone()),
ULE => self.backend.emit_jbe(blk_true.clone()),
ULT => self.backend.emit_jb (blk_true.clone()),
FOEQ | FUEQ => self.backend.emit_je (blk_true.clone()),
FONE | FUNE => self.backend.emit_jne(blk_true.clone()),
FOGT | FUGT => self.backend.emit_ja (blk_true.clone()),
FOGE | FUGE => self.backend.emit_jae(blk_true.clone()),
FOLT | FULT => self.backend.emit_jb (blk_true.clone()),
FOLE | FULE => self.backend.emit_jbe(blk_true.clone()),
_ => unimplemented!()
}
// mov false result here
self.emit_move_node_to_value(&tmp_res, &false_val, f_content, f_context, vm);
// jmp to end
self.backend.emit_jmp(blk_end.clone());
// finishing current block
let cur_block = self.current_block.as_ref().unwrap().clone();
self.backend.end_block(cur_block.clone());
// blk_true:
self.current_block = Some(blk_true.clone());
self.backend.start_block(blk_true.clone());
// mov true value -> result
self.emit_move_node_to_value(&tmp_res, &true_val, f_content, f_context, vm);
self.backend.end_block(blk_true.clone());
// blk_end:
self.backend.start_block(blk_end.clone());
self.current_block = Some(blk_end.clone());
}
}
} else {
// moving vectors, floatingpoints
......@@ -1902,6 +1948,8 @@ impl <'a> InstructionSelection {
let mut return_vals = vec![];
let mut gpr_ret_count = 0;
let mut fpr_ret_count = 0;
for ret_index in 0..sig.ret_tys.len() {
let ref ty = sig.ret_tys[ret_index];
......@@ -1927,8 +1975,18 @@ impl <'a> InstructionSelection {
// get return value by stack
unimplemented!()
}
} else {
} else if ret_val.is_fp_reg() {
// floating point register
if fpr_ret_count < x86_64::RETURN_FPRs.len() {
let ref ret_fpr = x86_64::RETURN_FPRs[fpr_ret_count];
self.backend.emit_movsd_f64_f64(&ret_val, &ret_fpr);
fpr_ret_count += 1;
} else {
// get return value by stack
unimplemented!()
}
} else {
unimplemented!()
}
......
......@@ -359,6 +359,9 @@ 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!("from: {:?}, to: {:?}", m.from, m.to);
return;
}
......@@ -407,7 +410,10 @@ impl <'a> GraphColoring<'a> {
}
} else if (precolored_u && self.ok(u, v))
|| (!precolored_u && self.conservative(u, v)) {
trace!("precolored_u&&ok(u,v) || !precolored_u&&conserv(u,v), coalesce and combine the move");
trace!("ok(u, v) = {}", self.ok(u, v));
trace!("conservative(u, v) = {}", self.conservative(u, v));
trace!("precolored_u&&ok(u,v) || !precolored_u&&conserv(u,v), coalesce and combine the move");
self.coalesced_moves.insert(m);
self.combine(u, v);
if !precolored_u {
......@@ -458,8 +464,7 @@ impl <'a> GraphColoring<'a> {
let mut k = 0;
for n in nodes.iter() {
// if self.precolored.contains(n) || self.degree(*n) >= self.n_regs_for_node(*n) {
if self.degree(*n) >= self.n_regs_for_node(*n) {
if self.precolored.contains(n) || self.degree(*n) >= self.n_regs_for_node(*n) {
k += 1;
}
}
......@@ -597,11 +602,17 @@ impl <'a> GraphColoring<'a> {
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();
trace!("all the colors for this temp: {:?}", ok_colors);
for w in self.ig.outedges_of(n) {
let w = self.get_alias(w);
match self.ig.get_color_of(w) {
let w_alias = self.get_alias(w);
match self.ig.get_color_of(w_alias) {
None => {}, // do nothing
Some(color) => {ok_colors.remove(&color);}
Some(color) => {
trace!("color {} is used for its neighbor {:?} (aliasing to {:?})", color, self.display_node(w), self.display_node(w_alias));
ok_colors.remove(&color);
}
}
}
trace!("available colors: {:?}", ok_colors);
......
......@@ -92,6 +92,27 @@ impl InterferenceGraph {
}
fn add_move(&mut self, src: NodeIndex, dst: NodeIndex) {
let src = {
let temp_src = self.get_temp_of(src);
if temp_src < MACHINE_ID_END {
let alias = backend::get_color_for_precolored(self.get_temp_of(src));
self.get_node(alias)
} else {
src
}
};
let dst = {
let temp_dst = self.get_temp_of(dst);
if temp_dst < MACHINE_ID_END {
let alias = backend::get_color_for_precolored(self.get_temp_of(dst));
self.get_node(alias)
} else {
dst
}
};
self.moves.insert(Move{from: src, to: dst});
}
......@@ -126,11 +147,8 @@ impl InterferenceGraph {
}
pub fn is_interferenced_with(&self, node1: NodeIndex, node2: NodeIndex) -> bool {
trace!("trying to find edge between {:?} and {:?}", node1, node2);
let edge = self.graph.find_edge(node1, node2);
trace!("edge: {:?}", edge);
edge.is_some()
}
......
......@@ -263,6 +263,64 @@ fn select_eq_zero() -> VM {
vm
}
#[test]
fn test_select_u8_eq_zero() {
let lib = testutil::compile_fnc("select_u8_eq_zero", &select_u8_eq_zero);
unsafe {
let select_eq_zero : libloading::Symbol<unsafe extern fn(u8) -> u8> = lib.get(b"select_u8_eq_zero").unwrap();
let res = select_eq_zero(0);
println!("select_u8_eq_zero(0) = {}", res);
assert!(res == 1);
let res = select_eq_zero(1);
println!("select_u8_eq_zero(1) = {}", res);
assert!(res == 0);
}
}
fn select_u8_eq_zero() -> VM {
let vm = VM::new();
typedef! ((vm) int8 = mu_int(8));
typedef! ((vm) int1 = mu_int(1));
constdef!((vm) <int8> int8_0 = Constant::Int(0));
constdef!((vm) <int8> int8_1 = Constant::Int(1));
funcsig! ((vm) sig = (int8) -> (int8));
funcdecl!((vm) <sig> select_u8_eq_zero);
funcdef! ((vm) <sig> select_u8_eq_zero VERSION select_u8_eq_zero_v1);
// blk entry
block! ((vm, select_u8_eq_zero_v1) blk_entry);
ssa! ((vm, select_u8_eq_zero_v1) <int8> blk_entry_n);
ssa! ((vm, select_u8_eq_zero_v1) <int1> blk_entry_cond);
consta!((vm, select_u8_eq_zero_v1) int8_0_local = int8_0);
consta!((vm, select_u8_eq_zero_v1) int8_1_local = int8_1);
inst! ((vm, select_u8_eq_zero_v1) blk_entry_inst_cmp:
blk_entry_cond = CMPOP (CmpOp::EQ) blk_entry_n int8_0_local
);
ssa! ((vm, select_u8_eq_zero_v1) <int8> blk_entry_ret);
inst! ((vm, select_u8_eq_zero_v1) blk_entry_inst_select:
blk_entry_ret = SELECT blk_entry_cond int8_1_local int8_0_local
);
inst! ((vm, select_u8_eq_zero_v1) blk_entry_inst_ret:
RET (blk_entry_ret)
);
define_block! ((vm, select_u8_eq_zero_v1) blk_entry(blk_entry_n){
blk_entry_inst_cmp, blk_entry_inst_select, blk_entry_inst_ret
});
define_func_ver!((vm) select_u8_eq_zero_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_select_sge_zero() {
let lib = testutil::compile_fnc("select_sge_zero", &select_sge_zero);
......
......@@ -161,14 +161,14 @@ def save_results(test_name, results):
def perf_fibonacci(N, iterations):
from perftarget.fibonacci import fib
from perftarget.fibonacci import fib, rpy_entry
tmpdir = py.path.local(mkdtemp())
print tmpdir
config = {
'py_file': perf_target_dir.join('fibonacci.py'),
'c_file': perf_target_dir.join('fibonacci.c'),
'rpy_fnc': fib,
'rpy_fnc': rpy_entry,
'c_sym_name': 'fib',
'llarg_ts': [lltype.Signed],
'llres_t': lltype.Signed,
......
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