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.

Commit 8dfa2bff authored by qinsoon's avatar qinsoon
Browse files

trace gen: layout blocks before instruction selection

parent 629e1960
......@@ -20,12 +20,14 @@ pub struct MuFunction {
pub fn_name: MuTag,
pub sig: P<MuFuncSig>,
pub content: Option<FunctionContent>,
pub context: FunctionContext
pub context: FunctionContext,
pub block_trace: Option<Vec<MuTag>> // only available after Trace Generation Pass
}
impl MuFunction {
pub fn new(fn_name: MuTag, sig: P<MuFuncSig>) -> MuFunction {
MuFunction{fn_name: fn_name, sig: sig, content: None, context: FunctionContext::new()}
MuFunction{fn_name: fn_name, sig: sig, content: None, context: FunctionContext::new(), block_trace: None}
}
pub fn define(&mut self, content: FunctionContent) {
......@@ -133,6 +135,26 @@ pub struct ControlFlow {
pub succs : Vec<BlockEdge>
}
impl ControlFlow {
pub fn get_hottest_succ(&self) -> Option<MuTag> {
if self.succs.len() == 0 {
None
} else {
let mut hot_blk = self.succs[0].target;
let mut hot_prob = self.succs[0].probability;
for edge in self.succs.iter() {
if edge.probability > hot_prob {
hot_blk = edge.target;
hot_prob = edge.probability;
}
}
Some(hot_blk)
}
}
}
impl fmt::Display for ControlFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "preds: [{}], ", vector_as_str(&self.preds)).unwrap();
......
mod def_use;
mod tree_gen;
mod control_flow;
mod trace_gen;
pub use compiler::passes::def_use::DefUse;
pub use compiler::passes::tree_gen::TreeGen;
pub use compiler::passes::control_flow::ControlFlowAnalysis;
\ No newline at end of file
pub use compiler::passes::control_flow::ControlFlowAnalysis;
pub use compiler::passes::trace_gen::TraceGen;
\ No newline at end of file
use ast::ir::*;
use vm::context::VMContext;
use compiler::CompilerPass;
pub struct TraceGen {
name: &'static str
}
impl TraceGen {
pub fn new() -> TraceGen {
TraceGen{name: "Trace Generation"}
}
}
impl CompilerPass for TraceGen {
fn name(&self) -> &'static str {
self.name
}
fn visit_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
// we put the high probability edge into a hot trace, and others into cold paths
// and traverse cold_path later
let trace = {
let mut trace : Vec<MuTag> = vec![];
let mut work_stack : Vec<MuTag> = vec![];
let entry = func.content.as_ref().unwrap().entry;
work_stack.push(entry);
while !work_stack.is_empty() {
let cur = work_stack.pop().unwrap();
let cur_block = func.content.as_ref().unwrap().get_block(&cur);
trace!("check block {}", cur);
trace!("add {:?} to trace", cur);
trace.push(cur);
let hot_edge = {
match cur_block.control_flow.get_hottest_succ() {
Some(tag) => tag,
None => continue
}
};
// push cold paths (that are not in the trace and not in the work_stack) to work_stack
let mut cold_edges = cur_block.control_flow.succs.clone();
cold_edges.retain(|x| !x.target.eq(hot_edge) && !trace.contains(&x.target) &&!work_stack.contains(&x.target));
let mut cold_edge_tags = cold_edges.iter().map(|x| x.target).collect::<Vec<MuTag>>();
trace!("push cold edges {:?} to work stack", cold_edge_tags);
work_stack.append(&mut cold_edge_tags);
// if hot edge is not in the trace, push it
if !trace.contains(&hot_edge) && !work_stack.contains(&hot_edge) {
trace!("push hot edge {:?} to work stack", hot_edge);
work_stack.push(hot_edge);
} else {
trace!("hot edge {:?} already in trace, ignore", hot_edge);
}
trace!("");
}
trace
};
func.block_trace = Some(trace);
}
fn finish_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
debug!("trace for {}", func.fn_name);
debug!("{:?}", func.block_trace.as_ref().unwrap());
}
}
\ No newline at end of file
......@@ -5,13 +5,19 @@ mod test_compiler;
mod common {
use std::fmt;
pub fn assert_str_vector (left: &Vec<&str>, right: &Vec<&str>) {
left.clone().sort();
right.clone().sort();
pub fn assert_vector_ordered <T: fmt::Debug> (left: &Vec<T>, right: &Vec<T>) {
assert_debug_str(left, right);
}
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();
let mut right_clone = right.clone();
right_clone.sort();
assert_debug_str(left_clone, right_clone);
}
pub fn assert_debug_str<T: fmt::Debug, U: fmt::Debug> (left: T, right: U) {
assert_eq!(format!("{:?}", left), format!("{:?}", right))
}
......
......@@ -73,18 +73,18 @@ fn test_cfa_factorial() {
// blk_0: preds=[], succs=[blk_2, blk_1]
let blk_0 = content.get_block("blk_0");
assert_str_vector(&blk_0.control_flow.preds, &vec![]);
assert_str_vector(&block_edges_into_vec(&blk_0.control_flow.succs), &vec!["blk_2", "blk_1"]);
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", "blk_1"]);
// blk_2: preds=[blk_0, blk_1], succs=[]
let blk_2 = content.get_block("blk_2");
assert_str_vector(&blk_2.control_flow.preds, &vec!["blk_0", "blk_1"]);
assert_str_vector(&block_edges_into_vec(&blk_2.control_flow.succs), &vec![]);
assert_vector_no_order(&blk_2.control_flow.preds, &vec!["blk_0", "blk_1"]);
assert_vector_no_order(&block_edges_into_vec(&blk_2.control_flow.succs), &vec![]);
// blk_1: preds=[blk_0], succs=[blk_2]
let blk_1 = content.get_block("blk_1");
assert_str_vector(&blk_1.control_flow.preds, &vec!["blk_0"]);
assert_str_vector(&block_edges_into_vec(&blk_1.control_flow.succs), &vec!["blk_2"]);
assert_vector_no_order(&blk_1.control_flow.preds, &vec!["blk_0"]);
assert_vector_no_order(&block_edges_into_vec(&blk_1.control_flow.succs), &vec!["blk_2"]);
}
#[test]
......@@ -109,18 +109,18 @@ fn test_cfa_sum() {
// entry: preds=[], succs=[head]
let entry = content.get_block("entry");
assert_str_vector(&entry.control_flow.preds, &vec![]);
assert_str_vector(&block_edges_into_vec(&entry.control_flow.succs), &vec!["head"]);
assert_vector_no_order(&entry.control_flow.preds, &vec![]);
assert_vector_no_order(&block_edges_into_vec(&entry.control_flow.succs), &vec!["head"]);
// head: preds=[entry, head], succs=[head, ret]
let head = content.get_block("head");
assert_str_vector(&head.control_flow.preds, &vec!["entry", "head"]);
assert_str_vector(&block_edges_into_vec(&head.control_flow.succs), &vec!["ret", "head"]);
assert_vector_no_order(&head.control_flow.preds, &vec!["entry", "head"]);
assert_vector_no_order(&block_edges_into_vec(&head.control_flow.succs), &vec!["ret", "head"]);
// ret: preds=[head], succs=[]
let ret = content.get_block("ret");
assert_str_vector(&ret.control_flow.preds, &vec!["head"]);
assert_str_vector(&block_edges_into_vec(&ret.control_flow.succs), &vec![]);
assert_vector_no_order(&ret.control_flow.preds, &vec!["head"]);
assert_vector_no_order(&block_edges_into_vec(&ret.control_flow.succs), &vec![]);
}
fn block_edges_into_vec(edges: &Vec<BlockEdge>) -> Vec<&str> {
......@@ -129,4 +129,46 @@ fn block_edges_into_vec(edges: &Vec<BlockEdge>) -> Vec<&str> {
ret.push(edge.target);
}
ret
}
#[test]
fn test_trace_factorial() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm_context : VMContext = factorial();
let compiler = Compiler::new(CompilerPolicy::new(vec![
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::ControlFlowAnalysis::new()),
Box::new(passes::TraceGen::new())
]));
let mut factorial_func = {
vm_context.get_func("fac").unwrap().borrow_mut()
};
compiler.compile(&vm_context, &mut factorial_func);
assert_vector_ordered(factorial_func.block_trace.as_ref().unwrap(), &vec!["blk_0", "blk_1", "blk_2"]);
}
#[test]
fn test_trace_sum() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm_context : VMContext = sum();
let compiler = Compiler::new(CompilerPolicy::new(vec![
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::ControlFlowAnalysis::new()),
Box::new(passes::TraceGen::new())
]));
let mut sum_func = {
vm_context.get_func("sum").unwrap().borrow_mut()
};
compiler.compile(&vm_context, &mut sum_func);
assert_vector_ordered(sum_func.block_trace.as_ref().unwrap(), &vec!["entry", "head", "ret"]);
}
\ No newline at end of file
......@@ -208,7 +208,7 @@ pub fn factorial() -> VMContext {
target: "blk_1",
args: vec![DestArg::Normal(2)]
},
true_prob: 0.5f32
true_prob: 0.3f32
}
});
......
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