Commit 6b06e94b authored by John Zhang's avatar John Zhang

Merge branch 'master' into jit-test

parents 93342ba2 c04159ca
......@@ -386,7 +386,7 @@ impl MachineCode for ASMCode {
}
}
fn replace_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize) {
fn replace_define_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize) {
let to_reg_string : MuName = match backend::all_regs().get(&to) {
Some(ref machine_reg) => {
let name = machine_reg.name().unwrap();
......@@ -408,8 +408,20 @@ impl MachineCode for ASMCode {
// remove old key, insert new one
asm.defines.remove(&from);
asm.defines.insert(from, define_locs);
asm.defines.insert(to, define_locs);
}
}
fn replace_use_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize) {
let to_reg_string : MuName = match backend::all_regs().get(&to) {
Some(ref machine_reg) => {
let name = machine_reg.name().unwrap();
"%".to_string() + &name
},
None => REG_PLACEHOLDER.clone()
};
let asm = &mut self.code[inst];
// if this reg is used, replace the use
if asm.uses.contains_key(&from) {
......@@ -423,7 +435,7 @@ impl MachineCode for ASMCode {
// remove old key, insert new one
asm.uses.remove(&from);
asm.uses.insert(from, use_locs);
asm.uses.insert(to, use_locs);
}
}
......@@ -1802,18 +1814,22 @@ pub fn spill_rewrite(
// iterate through all instructions
for i in 0..cf.mc().number_of_insts() {
trace!("---Inst {}---", i);
// find use of any register that gets spilled
{
let reg_uses = cf.mc().get_inst_reg_uses(i).to_vec();
for reg in reg_uses {
if spills.contains_key(&reg) {
let val_reg = func.context.get_value(reg).unwrap().value().clone();
// a register used here is spilled
let spill_mem = spills.get(&reg).unwrap();
// generate a random new temporary
let temp_ty = func.context.get_value(reg).unwrap().ty().clone();
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());
trace!("reg {} used in Inst{} is replaced as {}", val_reg, i, temp);
// generate a load
let code = {
......@@ -1832,7 +1848,7 @@ pub fn spill_rewrite(
}
// replace register reg with temp
cf.mc_mut().replace_tmp_for_inst(reg, temp.id(), i);
cf.mc_mut().replace_use_tmp_for_inst(reg, temp.id(), i);
}
}
}
......@@ -1842,11 +1858,14 @@ pub fn spill_rewrite(
let reg_defines = cf.mc().get_inst_reg_defines(i).to_vec();
for reg in reg_defines {
if spills.contains_key(&reg) {
let val_reg = func.context.get_value(reg).unwrap().value().clone();
let spill_mem = spills.get(&reg).unwrap();
let temp_ty = func.context.get_value(reg).unwrap().ty().clone();
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());
trace!("reg {} defined in Inst{} is replaced as {}", val_reg, i, temp);
let code = {
let mut codegen = ASMCodeGen::new();
......@@ -1863,7 +1882,7 @@ pub fn spill_rewrite(
spill_code_after.insert(i, vec![code]);
}
cf.mc_mut().replace_tmp_for_inst(reg, temp.id(), i);
cf.mc_mut().replace_define_tmp_for_inst(reg, temp.id(), i);
}
}
}
......
......@@ -236,14 +236,8 @@ lazy_static! {
map
};
// put callee saved regs first
// put caller saved regs first (they imposes no overhead if there is no call instruction)
pub static ref ALL_USABLE_MACHINE_REGs : Vec<P<Value>> = vec![
RBX.clone(),
R12.clone(),
R13.clone(),
R14.clone(),
R15.clone(),
RAX.clone(),
RCX.clone(),
RDX.clone(),
......@@ -253,6 +247,13 @@ lazy_static! {
R9.clone(),
R10.clone(),
R11.clone(),
RBX.clone(),
R12.clone(),
R13.clone(),
R14.clone(),
R15.clone(),
XMM0.clone(),
XMM1.clone(),
XMM2.clone(),
......
......@@ -3,7 +3,6 @@ use compiler::backend;
use compiler::backend::reg_alloc::graph_coloring;
use compiler::backend::reg_alloc::graph_coloring::liveness::InterferenceGraph;
use compiler::backend::reg_alloc::graph_coloring::liveness::{Node, Move};
use compiler::backend::reg_alloc::RegAllocFailure;
use compiler::machine_code::CompiledFunction;
use vm::VM;
......@@ -49,12 +48,13 @@ pub struct GraphColoring<'a> {
}
impl <'a> GraphColoring<'a> {
pub fn start (func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> Result<GraphColoring<'a>, RegAllocFailure> {
pub fn start (func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> GraphColoring<'a> {
trace!("Initializing coloring allocator...");
cf.mc().trace_mc();
let ig = graph_coloring::build_inteference_graph(cf, func);
let mut coloring = GraphColoring {
let coloring = GraphColoring {
func: func,
cf: cf,
vm: vm,
......@@ -108,9 +108,7 @@ impl <'a> GraphColoring<'a> {
format!("Move: {} -> {}", self.display_node(m.from), self.display_node(m.to))
}
fn regalloc(mut self) -> Result<GraphColoring<'a>, RegAllocFailure> {
trace!("Initializing coloring allocator...");
fn regalloc(mut self) -> GraphColoring<'a> {
trace!("---InterenceGraph---");
self.ig.print(&self.func.context);
......@@ -174,7 +172,7 @@ impl <'a> GraphColoring<'a> {
return GraphColoring::start(self.func, self.cf, self.vm);
}
Ok(self)
self
}
fn build(&mut self) {
......@@ -584,7 +582,7 @@ impl <'a> GraphColoring<'a> {
self.freeze_moves(m);
}
fn assign_colors(&mut self) -> Result<(), ()> {
fn assign_colors(&mut self) {
trace!("---coloring done---");
while !self.select_stack.is_empty() {
let n = self.select_stack.pop().unwrap();
......@@ -625,8 +623,6 @@ impl <'a> GraphColoring<'a> {
trace!("Color {} as {}", self.display_node(n), alias_color);
self.ig.color_node(n, alias_color);
}
Ok(())
}
fn rewrite_program(&mut self) {
......@@ -646,30 +642,6 @@ impl <'a> GraphColoring<'a> {
}
let new_temps = backend::spill_rewrite(&spilled_mem, self.func, self.cf, self.vm);
//
// self.spilled_nodes.clear();
//
// self.initial = {
// let mut ret = vec![];
//
// for node in self.colored_nodes.iter() {
// vec_utils::add_unique(&mut ret, node.clone());
// }
// for node in self.coalesced_nodes.iter() {
// vec_utils::add_unique(&mut ret, node.clone());
// }
//
// // create nodes for every new temp
// for tmp in new_temps {
// let node = self.ig.new_node(tmp.id(), &func.context);
// vec_utils::add_unique(&mut ret, node.clone());
// }
//
// ret
// };
//
// self.colored_nodes.clear();
// self.coalesced_nodes.clear();
}
pub fn spills(&self) -> Vec<MuID> {
......
......@@ -263,14 +263,6 @@ impl InterferenceGraph {
}
}
pub fn is_machine_reg(reg: MuID) -> bool {
if reg < MACHINE_ID_END {
true
} else {
false
}
}
#[allow(unused_variables)]
fn build_live_set(cf: &mut CompiledFunction, func: &MuFunctionVersion) {
let n_insts = cf.mc().number_of_insts();
......@@ -321,15 +313,11 @@ fn build_live_set(cf: &mut CompiledFunction, func: &MuFunctionVersion) {
}
for block in cf.mc().get_all_blocks().to_vec() {
if cf.mc().get_ir_block_livein(&block).is_none() {
let start_inst = cf.mc().get_block_range(&block).unwrap().start;
cf.mc_mut().set_ir_block_livein(&block, livein[start_inst].to_vec());
}
if cf.mc().get_ir_block_liveout(&block).is_none() {
let end_inst = cf.mc().get_block_range(&block).unwrap().end;
cf.mc_mut().set_ir_block_liveout(&block, liveout[end_inst].to_vec());
}
let start_inst = cf.mc().get_block_range(&block).unwrap().start;
cf.mc_mut().set_ir_block_livein(&block, livein[start_inst].to_vec());
let end_inst = cf.mc().get_block_range(&block).unwrap().end;
cf.mc_mut().set_ir_block_liveout(&block, liveout[end_inst].to_vec());
}
}
......
......@@ -8,14 +8,8 @@ pub use compiler::backend::reg_alloc::graph_coloring::coloring::GraphColoring;
use ast::ir::*;
use vm::VM;
use compiler;
use compiler::CompilerPass;
use compiler::PassExecutionResult;
use compiler::backend::init_machine_regs_for_func;
use compiler::backend;
use compiler::backend::reg_alloc::RegAllocFailure;
use std::collections::HashMap;
use std::any::Any;
pub struct RegisterAllocation {
......@@ -30,17 +24,14 @@ impl RegisterAllocation {
}
#[allow(unused_variables)]
fn coloring(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> Result<(), RegAllocFailure> {
fn coloring(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
// initialize machine registers for the function context
init_machine_regs_for_func(&mut func.context);
let coloring = match GraphColoring::start(func, &mut cf, vm) {
Ok(coloring) => coloring,
Err(_) => panic!("error during coloring - unexpected")
};
let coloring = GraphColoring::start(func, &mut cf, vm);
// replace regs
trace!("Replacing Registers...");
......@@ -68,8 +59,6 @@ impl RegisterAllocation {
}
coloring.cf.mc().trace_mc();
Ok(())
}
}
......@@ -82,15 +71,7 @@ impl CompilerPass for RegisterAllocation {
self
}
fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> PassExecutionResult {
debug!("---CompilerPass {} for {}---", self.name(), func);
match self.coloring(vm, func) {
// skip slow path
Ok(_) => PassExecutionResult::ProceedTo(compiler::PASS_PEEPHOLE),
// go back to instruction selection for spilled operands
Err(RegAllocFailure::FailedForSpilling) => PassExecutionResult::GoBackTo(compiler::PASS_INST_SEL),
}
fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
self.coloring(vm, func);
}
}
pub mod graph_coloring;
pub enum RegAllocFailure {
FailedForSpilling,
}
pub use compiler::backend::reg_alloc::graph_coloring::RegisterAllocation;
\ No newline at end of file
......@@ -123,7 +123,8 @@ pub trait MachineCode {
/// replace a temp with a machine register (to_reg must be a machine register)
fn replace_reg(&mut self, from: MuID, to: MuID);
/// replace a temp with another temp
fn replace_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
fn replace_define_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
fn replace_use_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
fn set_inst_nop(&mut self, index: usize);
fn as_any(&self) -> &Any;
......
......@@ -12,16 +12,6 @@ pub mod frame;
pub mod machine_code;
pub use compiler::passes::CompilerPass;
pub use compiler::passes::PassExecutionResult;
pub use compiler::passes::PASS_IR_CHECK;
pub use compiler::passes::PASS_DEF_USE;
pub use compiler::passes::PASS_TREE_GEN;
pub use compiler::passes::PASS_CFA;
pub use compiler::passes::PASS_TRACE_GEN;
pub use compiler::passes::PASS_INST_SEL;
pub use compiler::passes::PASS_REG_ALLOC;
pub use compiler::passes::PASS_PEEPHOLE;
pub use compiler::passes::PASS_CODE_EMIT;
pub struct Compiler {
policy: RefCell<CompilerPolicy>,
......@@ -42,20 +32,12 @@ impl Compiler {
// FIXME: should use function name here (however hprof::enter only accept &'static str)
let _p = hprof::enter("Function Compilation");
let mut cur_pass = 0;
let n_passes = self.policy.borrow().passes.len();
let ref mut passes = self.policy.borrow_mut().passes;
while cur_pass < n_passes {
let _p = hprof::enter(passes[cur_pass].name());
let result = passes[cur_pass].execute(&self.vm, func);
for pass in passes.iter_mut() {
let _p = hprof::enter(pass.name());
match result {
PassExecutionResult::ProceedToNext => cur_pass += 1,
PassExecutionResult::ProceedTo(next)
| PassExecutionResult::GoBackTo(next) => cur_pass = next.get()
}
pass.execute(&self.vm, func);
drop(_p);
}
......
......@@ -6,32 +6,11 @@ mod tree_gen;
mod control_flow;
mod trace_gen;
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct PassID(usize);
impl PassID {pub fn get(&self) -> usize{self.0}}
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;
// make sure the pass IDs are sequential
pub const PASS_IR_CHECK : PassID = PassID(0);
pub const PASS_DEF_USE : PassID = PassID(1);
pub const PASS_TREE_GEN : PassID = PassID(2);
pub const PASS_CFA : PassID = PassID(3);
pub const PASS_TRACE_GEN : PassID = PassID(4);
pub const PASS_INST_SEL : PassID = PassID(5);
pub const PASS_REG_ALLOC : PassID = PassID(6);
pub const PASS_PEEPHOLE : PassID = PassID(7);
pub const PASS_CODE_EMIT : PassID = PassID(8);
pub enum PassExecutionResult {
ProceedToNext,
ProceedTo(PassID),
GoBackTo(PassID)
}
use std::any::Any;
#[allow(unused_variables)]
......@@ -39,7 +18,7 @@ pub trait CompilerPass {
fn name(&self) -> &'static str;
fn as_any(&self) -> &Any;
fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> PassExecutionResult {
fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
debug!("---CompilerPass {} for {}---", self.name(), func);
self.start_function(vm, func);
......@@ -47,8 +26,6 @@ pub trait CompilerPass {
self.finish_function(vm, func);
debug!("---finish---");
PassExecutionResult::ProceedToNext
}
fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
......
......@@ -4,7 +4,6 @@ use ast::ir_semantics::*;
use vm::VM;
use compiler::CompilerPass;
use compiler::PassExecutionResult;
use std::any::Any;
......@@ -31,7 +30,7 @@ impl CompilerPass for TreeGen {
self
}
fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> PassExecutionResult {
fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
debug!("---CompilerPass {} for {}---", self.name(), func);
{
......@@ -123,8 +122,6 @@ impl CompilerPass for TreeGen {
self.finish_function(vm, func);
debug!("---finish---");
PassExecutionResult::ProceedToNext
}
#[allow(unused_variables)]
......
......@@ -74,111 +74,6 @@ fn test_ir_liveness_fac() {
assert!(vec_utils::is_identical_to_str_ignore_order(block_2_liveout, expect));
}
use mu::compiler::backend::reg_alloc::graph_coloring::GraphColoring;
use mu::compiler::backend::reg_alloc::graph_coloring::InterferenceGraph;
use mu::compiler::backend::init_machine_regs_for_func;
use std::any::Any;
struct InspectInterferenceGraph {
name: &'static str,
ig: Option<InterferenceGraph>,
}
impl InspectInterferenceGraph {
pub fn new() -> InspectInterferenceGraph {
InspectInterferenceGraph {
name: "Inspect Interference Graph",
ig: None
}
}
}
impl CompilerPass for InspectInterferenceGraph {
fn name(&self) -> &'static str {
self.name
}
fn as_any(&self) -> &Any {
self
}
fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> PassExecutionResult {
debug!("---CompilerPass {} for {}---", self.name(), func);
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
// initialize machine registers for the function context
init_machine_regs_for_func(&mut func.context);
let coloring = match GraphColoring::start(func, &mut cf, vm) {
Ok(coloring) => coloring,
Err(_) => panic!("error during coloring - unexpected")
};
self.ig = Some(coloring.ig);
PassExecutionResult::ProceedToNext
}
}
#[test]
#[allow(unused_variables)]
fn test_spill1_ig() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm = Arc::new(create_spill1());
let compiler = Compiler::new(CompilerPolicy::new({
let mut passes : Vec<Box<CompilerPass>> = vec![];
passes.push(Box::new(passes::DefUse::new()));
passes.push(Box::new(passes::TreeGen::new()));
passes.push(Box::new(passes::ControlFlowAnalysis::new()));
passes.push(Box::new(passes::TraceGen::new()));
// compilation
passes.push(Box::new(backend::inst_sel::InstructionSelection::new()));
passes.push(Box::new(InspectInterferenceGraph::new()));
passes
}), vm.clone());
let func_id = vm.id_of("spill1");
{
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 compiler_policy = compiler.get_policy().borrow();
let inspect_ig : &InspectInterferenceGraph = compiler_policy.passes[5].as_any().downcast_ref().unwrap();
let ig = inspect_ig.ig.as_ref().unwrap();
let t1 = ig.get_node(vm.id_of("blk_entry_t1"));
let t2 = ig.get_node(vm.id_of("blk_entry_t2"));
let t3 = ig.get_node(vm.id_of("blk_entry_t3"));
let t4 = ig.get_node(vm.id_of("blk_entry_t4"));
let t5 = ig.get_node(vm.id_of("blk_entry_t5"));
let t6 = ig.get_node(vm.id_of("blk_entry_t6"));
let t7 = ig.get_node(vm.id_of("blk_entry_t7"));
let t8 = ig.get_node(vm.id_of("blk_entry_t8"));
let t9 = ig.get_node(vm.id_of("blk_entry_t9"));
let t10= ig.get_node(vm.id_of("blk_entry_t10"));
let res0 = ig.get_node(vm.id_of("blk_entry_res0"));
let res1 = ig.get_node(vm.id_of("blk_entry_res1"));
let res2 = ig.get_node(vm.id_of("blk_entry_res2"));
let res3 = ig.get_node(vm.id_of("blk_entry_res3"));
// t1 interferes with t2
assert!(ig.is_interferenced_with(t1, t2));
}
#[test]
#[allow(unused_variables)]
fn test_spill1() {
......@@ -208,6 +103,8 @@ fn test_spill1() {
Ok(symbol) => symbol,
Err(e) => panic!("cannot find symbol spill1 in dylib: {:?}", e)
};
// we cannot call this (it doesnt return)
}
}
......
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