Commit 61d3bf99 authored by John Zhang's avatar John Zhang

Merge branch 'master' of gitlab.anu.edu.au:mu/mu-impl-fast

parents 65655a3e 47e9b088
Pipeline #154 failed with stage
in 14 minutes and 50 seconds
......@@ -266,7 +266,10 @@ pub enum Instruction_ {
// common inst
CommonInst_GetThreadLocal,
CommonInst_SetThreadLocal(OpIndex)
CommonInst_SetThreadLocal(OpIndex),
// internal use: mov from ops[0] to value
Move(OpIndex)
}
impl Instruction_ {
......@@ -379,8 +382,13 @@ impl Instruction_ {
&Instruction_::ExnInstruction{ref inner, ref resume} => {
format!("{} {}", inner.debug_str(ops), resume.debug_str(ops))
},
// common inst
&Instruction_::CommonInst_GetThreadLocal => format!("COMMONINST GetThreadLocal"),
&Instruction_::CommonInst_SetThreadLocal(op) => format!("COMMONINST SetThreadLocal {}", ops[op])
&Instruction_::CommonInst_SetThreadLocal(op) => format!("COMMONINST SetThreadLocal {}", ops[op]),
// move
&Instruction_::Move(from) => format!("MOVE {}", ops[from])
}
}
}
......
......@@ -568,6 +568,14 @@ impl Value {
}
}
pub unsafe fn as_type(&self, ty: P<MuType>) -> P<Value> {
P(Value{
hdr: self.hdr.clone(),
ty: ty,
v: self.v.clone()
})
}
pub fn is_fp_reg(&self) -> bool {
match self.v {
Value_::SSAVar(_) => {
......
......@@ -28,7 +28,8 @@ pub fn is_terminal_inst(inst: &Instruction_) -> bool {
| &Select{..}
| &Fence(_)
| &CommonInst_GetThreadLocal
| &CommonInst_SetThreadLocal(_) => false,
| &CommonInst_SetThreadLocal(_)
| &Move(_) => false,
&Return(_)
| &ThreadExit
| &Throw(_)
......@@ -91,5 +92,6 @@ pub fn has_side_effect(inst: &Instruction_) -> bool {
&ExnInstruction{..} => true,
&CommonInst_GetThreadLocal => true,
&CommonInst_SetThreadLocal(_) => true,
&Move(_) => false,
}
}
......@@ -59,7 +59,9 @@ pub enum OpCode {
GetVarPartIRef,
CommonInst_GetThreadLocal,
CommonInst_SetThreadLocal
CommonInst_SetThreadLocal,
Move
}
pub fn pick_op_code_for_ssa(ty: &P<MuType>) -> OpCode {
......@@ -285,6 +287,7 @@ pub fn pick_op_code_for_inst(inst: &Instruction) -> OpCode {
Instruction_::Switch{..} => OpCode::Switch,
Instruction_::ExnInstruction{..} => OpCode::ExnInstruction,
Instruction_::CommonInst_GetThreadLocal => OpCode::CommonInst_GetThreadLocal,
Instruction_::CommonInst_SetThreadLocal(_) => OpCode::CommonInst_SetThreadLocal
Instruction_::CommonInst_SetThreadLocal(_) => OpCode::CommonInst_SetThreadLocal,
Instruction_::Move(_) => OpCode::Move,
}
}
#![allow(unused_variables)]
use compiler::backend;
use compiler::backend::AOT_EMIT_CONTEXT_FILE;
use compiler::backend::AOT_EMIT_DIR;
use compiler::backend::RegGroup;
......
......@@ -436,9 +436,9 @@ pub fn is_callee_saved(reg_id: MuID) -> bool {
}
pub fn is_valid_x86_imm(op: &P<Value>) -> bool {
use std::i32;
use std::u32;
match op.v {
Value_::Constant(Constant::Int(val)) if val <= i32::MAX as u64 => {
Value_::Constant(Constant::Int(val)) if val <= u32::MAX as u64 => {
true
},
_ => false
......
......@@ -6,7 +6,6 @@ use compiler::backend;
use utils::vec_utils;
use utils::LinkedHashSet;
use std::collections::LinkedList;
use std::collections::{HashMap, HashSet};
use self::nalgebra::DMatrix;
......
......@@ -67,6 +67,7 @@ impl Default for CompilerPolicy {
// ir level passes
passes.push(Box::new(passes::DefUse::new()));
passes.push(Box::new(passes::TreeGen::new()));
passes.push(Box::new(passes::GenMovPhi::new()));
passes.push(Box::new(passes::ControlFlowAnalysis::new()));
passes.push(Box::new(passes::TraceGen::new()));
......
This diff is collapsed.
......@@ -5,11 +5,13 @@ mod def_use;
mod tree_gen;
mod control_flow;
mod trace_gen;
mod gen_mov_phi;
pub use compiler::passes::def_use::DefUse;
pub use compiler::passes::tree_gen::TreeGen;
pub use compiler::passes::control_flow::ControlFlowAnalysis;
pub use compiler::passes::trace_gen::TraceGen;
pub use compiler::passes::gen_mov_phi::GenMovPhi;
use std::any::Any;
......
......@@ -14,11 +14,13 @@ mod test_api;
mod common {
use std::fmt;
#[allow(dead_code)]
pub fn assert_vector_ordered <T: fmt::Debug> (left: &Vec<T>, right: &Vec<T>) {
assert_debug_str(left, right);
}
#[allow(dead_code)]
pub fn assert_vector_no_order <T: Ord + fmt::Debug + Clone> (left: &Vec<T>, right: &Vec<T>) {
let mut left_clone = left.clone();
left_clone.sort();
......@@ -27,7 +29,8 @@ mod common {
assert_debug_str(left_clone, right_clone);
}
#[allow(dead_code)]
pub fn assert_debug_str<T: fmt::Debug, U: fmt::Debug> (left: T, right: U) {
assert_eq!(format!("{:?}", left), format!("{:?}", right))
}
......
......@@ -54,6 +54,59 @@ fn test_build_tree() {
compiler.compile(&mut func_ver);
}
// consider one intermediate block
fn is_successor(from_id: MuID, to_id: MuID, content: &FunctionContent) -> bool {
let blk_from = content.get_block(from_id);
for outedge in blk_from.control_flow.succs.iter() {
if outedge.target == to_id {
return true;
}
let intermediate_block = content.get_block(outedge.target);
for int_outedge in intermediate_block.control_flow.succs.iter() {
if int_outedge.target == to_id {
return true;
}
}
}
return false;
}
fn has_successor(id: MuID, content: &FunctionContent) -> bool {
let blk = content.get_block(id);
!blk.control_flow.succs.is_empty()
}
fn is_predecessor(from_id: MuID, to_id: MuID, content: &FunctionContent) -> bool {
let blk_from = content.get_block(from_id);
for pred in blk_from.control_flow.preds.iter() {
if *pred == to_id {
return true;
}
let intermediate_block = content.get_block(*pred);
for int_pred in intermediate_block.control_flow.preds.iter() {
if *int_pred == to_id {
return true;
}
}
}
return false;
}
fn has_predecessor(id: MuID, content: &FunctionContent) -> bool {
let blk = content.get_block(id);
!blk.control_flow.preds.is_empty()
}
#[test]
fn test_cfa_factorial() {
VM::start_logging_trace();
......@@ -62,6 +115,7 @@ fn test_cfa_factorial() {
let compiler = Compiler::new(CompilerPolicy::new(vec![
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::GenMovPhi::new()),
Box::new(passes::ControlFlowAnalysis::new())
]), vm.clone());
......@@ -75,23 +129,28 @@ fn test_cfa_factorial() {
// assert cfa
let content = func_ver.content.as_ref().unwrap();
// blk_0: preds=[], succs=[blk_2, blk_1]
let (blk_0_id, blk_1_id, blk_2_id) = (vm.id_of("blk_0"), vm.id_of("blk_1"), vm.id_of("blk_2"));
let blk_0 = content.get_block(blk_0_id);
assert_vector_no_order(&blk_0.control_flow.preds, &vec![]);
assert_vector_no_order(&block_edges_into_vec(&blk_0.control_flow.succs), &vec![blk_2_id, blk_1_id]);
// blk_0: preds=[], succs=[blk_2, blk_1] - however there will be intermediate block
// check blk_0 predecessor
assert!(!has_predecessor(blk_0_id, content));
// check blk_0 successor
assert!(is_successor(blk_0_id, blk_1_id, content));
assert!(is_successor(blk_0_id, blk_2_id, content));
// blk_2: preds=[blk_0, blk_1], succs=[]
let blk_2 = content.get_block(blk_2_id);
assert_vector_no_order(&blk_2.control_flow.preds, &vec![blk_0_id, blk_1_id]);
assert_vector_no_order(&block_edges_into_vec(&blk_2.control_flow.succs), &vec![]);
// check blk_2 predecessor
assert!(is_predecessor(blk_2_id, blk_0_id, content));
assert!(is_predecessor(blk_2_id, blk_1_id, content));
// check blk_2 successor
assert!(!has_successor(blk_2_id, content));
// blk_1: preds=[blk_0], succs=[blk_2]
let blk_1 = content.get_block(blk_1_id);
assert_vector_no_order(&blk_1.control_flow.preds, &vec![blk_0_id]);
assert_vector_no_order(&block_edges_into_vec(&blk_1.control_flow.succs), &vec![blk_2_id]);
// check blk_1 predecessor
assert!(is_predecessor(blk_1_id, blk_0_id, content));
// check blk_1 successor
assert!(is_successor(blk_1_id, blk_2_id, content));
}
#[test]
......@@ -102,6 +161,7 @@ fn test_cfa_sum() {
let compiler = Compiler::new(CompilerPolicy::new(vec![
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::GenMovPhi::new()),
Box::new(passes::ControlFlowAnalysis::new())
]), vm.clone());
......@@ -116,32 +176,46 @@ fn test_cfa_sum() {
// assert cfa
let content = func_ver.content.as_ref().unwrap();
let entry_id = vm.id_of("entry");
let head_id = vm.id_of("head");
let ret_id = vm.id_of("ret");
let entry = vm.id_of("entry");
let head = vm.id_of("head");
let ret = vm.id_of("ret");
// entry: preds=[], succs=[head]
let entry = content.get_block(entry_id);
assert_vector_no_order(&entry.control_flow.preds, &vec![]);
assert_vector_no_order(&block_edges_into_vec(&entry.control_flow.succs), &vec![head_id]);
assert!(!has_predecessor(entry, content));
assert!(is_successor(entry, head, content));
// head: preds=[entry, head], succs=[head, ret]
let head = content.get_block(head_id);
assert_vector_no_order(&head.control_flow.preds, &vec![entry_id, head_id]);
assert_vector_no_order(&block_edges_into_vec(&head.control_flow.succs), &vec![ret_id, head_id]);
assert!(is_predecessor(head, entry, content));
assert!(is_predecessor(head, head, content));
assert!(is_successor(head, head, content));
assert!(is_successor(head, ret, content));
// ret: preds=[head], succs=[]
let ret = content.get_block(ret_id);
assert_vector_no_order(&ret.control_flow.preds, &vec![head_id]);
assert_vector_no_order(&block_edges_into_vec(&ret.control_flow.succs), &vec![]);
assert!(is_predecessor(ret, head, content));
assert!(!has_successor(ret, content));
}
fn block_edges_into_vec(edges: &Vec<BlockEdge>) -> Vec<MuID> {
let mut ret = vec![];
for edge in edges {
ret.push(edge.target);
// as long as expected appears in correct order in actual, it is correct
fn match_trace(actual: &Vec<MuID>, expected: &Vec<MuID>) -> bool {
assert!(actual.len() >= expected.len());
debug!("matching trace:");
debug!("actual: {:?}", actual);
debug!("expected: {:?}", expected);
let mut expected_cursor = 0;
for i in actual {
if *i == expected[expected_cursor] {
expected_cursor += 1;
if expected_cursor == expected.len() {
return true;
}
}
}
ret
return false;
}
#[test]
......@@ -152,6 +226,7 @@ fn test_trace_factorial() {
let compiler = Compiler::new(CompilerPolicy::new(vec![
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::GenMovPhi::new()),
Box::new(passes::ControlFlowAnalysis::new()),
Box::new(passes::TraceGen::new())
]), vm.clone());
......@@ -163,8 +238,11 @@ fn test_trace_factorial() {
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
assert_vector_ordered(func_ver.block_trace.as_ref().unwrap(), &vec![vm.id_of("blk_0"), vm.id_of("blk_1"), vm.id_of("blk_2")]);
assert!(match_trace(
func_ver.block_trace.as_ref().unwrap(),
&vec![vm.id_of("blk_0"), vm.id_of("blk_1"), vm.id_of("blk_2")]
));
}
#[test]
......@@ -175,6 +253,7 @@ fn test_trace_sum() {
let compiler = Compiler::new(CompilerPolicy::new(vec![
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::GenMovPhi::new()),
Box::new(passes::ControlFlowAnalysis::new()),
Box::new(passes::TraceGen::new())
]), vm.clone());
......@@ -186,6 +265,9 @@ fn test_trace_sum() {
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
assert_vector_ordered(func_ver.block_trace.as_ref().unwrap(), &vec![vm.id_of("entry"), vm.id_of("head"), vm.id_of("ret")]);
assert!(match_trace(
func_ver.block_trace.as_ref().unwrap(),
&vec![vm.id_of("entry"), vm.id_of("head"), vm.id_of("ret")]
));
}
......@@ -104,14 +104,14 @@ pub fn sum() -> VM {
v: Instruction_::BinOp(BinOp::Add, 0, 1)
});
// %cond = UGT %i %n
// %cond = UGE %i %n
let blk_head_cond = func_ver.new_ssa(vm.next_id(), type_def_int1.clone());
vm.set_name(blk_head_cond.as_entity(), "blk_head_cond".to_string());
let blk_head_inst2 = func_ver.new_inst(Instruction {
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![blk_head_cond.clone_value()]),
ops: RwLock::new(vec![blk_head_i.clone(), blk_head_n.clone()]),
v: Instruction_::CmpOp(CmpOp::UGT, 0, 1)
v: Instruction_::CmpOp(CmpOp::UGE, 0, 1)
});
// BRANCH2 %cond %ret(%s2) %head(%n %s2 %i2)
......
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