Commit 97304444 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

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

parents a684c62a 8dc8cb77
...@@ -3747,7 +3747,6 @@ impl <'a> InstructionSelection { ...@@ -3747,7 +3747,6 @@ impl <'a> InstructionSelection {
// Note: the stack pointer should now be what it was when the function was called // Note: the stack pointer should now be what it was when the function was called
self.backend.emit_ret(&LR); // return to the Link Register self.backend.emit_ret(&LR); // return to the Link Register
//self.backend.emit_fake_ret();
self.finish_block(); self.finish_block();
} }
......
...@@ -667,9 +667,7 @@ lazy_static! { ...@@ -667,9 +667,7 @@ lazy_static! {
D15.clone() D15.clone()
]; ];
pub static ref ALL_USABLE_GPRS : Vec<P<Value>> = vec![
// 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![
X0.clone(), X0.clone(),
X1.clone(), X1.clone(),
X2.clone(), X2.clone(),
...@@ -702,7 +700,9 @@ lazy_static! { ...@@ -702,7 +700,9 @@ lazy_static! {
X28.clone(), X28.clone(),
//X29.clone(), // Frame Pointer //X29.clone(), // Frame Pointer
//X30.clone(), // Link Register //X30.clone(), // Link Register
];
pub static ref ALL_USABLE_FPRS : Vec<P<Value>> = vec![
D0.clone(), D0.clone(),
D1.clone(), D1.clone(),
D2.clone(), D2.clone(),
...@@ -738,6 +738,14 @@ lazy_static! { ...@@ -738,6 +738,14 @@ lazy_static! {
D14.clone(), D14.clone(),
D15.clone(), D15.clone(),
]; ];
// 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>> = {
let mut ret = vec![];
ret.extend_from_slice(&ALL_USABLE_GPRS);
ret.extend_from_slice(&ALL_USABLE_FPRS);
ret
};
} }
pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) { pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
...@@ -749,7 +757,7 @@ pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) { ...@@ -749,7 +757,7 @@ pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
} }
} }
pub fn number_of_regs_in_group(group: RegGroup) -> usize { pub fn number_of_usable_regs_in_group(group: RegGroup) -> usize {
match group { match group {
RegGroup::GPR => ALL_GPRS.len(), RegGroup::GPR => ALL_GPRS.len(),
RegGroup::FPR => ALL_FPRS.len(), RegGroup::FPR => ALL_FPRS.len(),
......
...@@ -436,11 +436,11 @@ lazy_static! { ...@@ -436,11 +436,11 @@ lazy_static! {
map map
}; };
/// all the usable registers for register allocators to assign /// all the usable general purpose registers for reg allocator to assign
// order matters here (since register allocator will prioritize assigning temporaries // order matters here (since register allocator will prioritize assigning temporaries
// to a register that appears early) // to a register that appears early)
// we put caller saved regs first (they imposes no overhead if there is no call instruction) // we 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![ pub static ref ALL_USABLE_GPRS : Vec<P<Value>> = vec![
// caller saved registers // caller saved registers
RAX.clone(), RAX.clone(),
RCX.clone(), RCX.clone(),
...@@ -457,6 +457,13 @@ lazy_static! { ...@@ -457,6 +457,13 @@ lazy_static! {
R13.clone(), R13.clone(),
R14.clone(), R14.clone(),
R15.clone(), R15.clone(),
];
/// all the usable floating point registers for reg allocator to assign
// order matters here (since register allocator will prioritize assigning temporaries
// to a register that appears early)
// we put caller saved regs first (they imposes no overhead if there is no call instruction)
pub static ref ALL_USABLE_FPRS : Vec<P<Value>> = vec![
// floating point registers // floating point registers
XMM0.clone(), XMM0.clone(),
XMM1.clone(), XMM1.clone(),
...@@ -475,6 +482,17 @@ lazy_static! { ...@@ -475,6 +482,17 @@ lazy_static! {
XMM14.clone(), XMM14.clone(),
XMM15.clone() XMM15.clone()
]; ];
/// all the usable registers for register allocators to assign
// order matters here (since register allocator will prioritize assigning temporaries
// to a register that appears early)
// we 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>> = {
let mut ret = vec![];
ret.extend_from_slice(&ALL_USABLE_GPRS);
ret.extend_from_slice(&ALL_USABLE_FPRS);
ret
};
} }
/// creates context for each machine register in FunctionContext /// creates context for each machine register in FunctionContext
...@@ -488,11 +506,11 @@ pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) { ...@@ -488,11 +506,11 @@ pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
} }
/// gets the number of registers in a certain register group /// gets the number of registers in a certain register group
pub fn number_of_regs_in_group(group: RegGroup) -> usize { pub fn number_of_usable_regs_in_group(group: RegGroup) -> usize {
match group { match group {
RegGroup::GPR => ALL_GPRS.len(), RegGroup::GPR => ALL_USABLE_GPRS.len(),
RegGroup::GPREX => ALL_GPRS.len(), RegGroup::GPREX => ALL_USABLE_GPRS.len(),
RegGroup::FPR => ALL_FPRS.len() RegGroup::FPR => ALL_USABLE_FPRS.len()
} }
} }
......
...@@ -63,7 +63,7 @@ pub use compiler::backend::x86_64::is_aliased; ...@@ -63,7 +63,7 @@ pub use compiler::backend::x86_64::is_aliased;
pub use compiler::backend::x86_64::get_color_for_precolored; pub use compiler::backend::x86_64::get_color_for_precolored;
/// returns the number of registers in a given RegGroup /// returns the number of registers in a given RegGroup
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::number_of_regs_in_group; pub use compiler::backend::x86_64::number_of_usable_regs_in_group;
/// returns the number of all machine registers /// returns the number of all machine registers
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::number_of_all_regs; pub use compiler::backend::x86_64::number_of_all_regs;
...@@ -138,7 +138,7 @@ pub use compiler::backend::aarch64::is_aliased; ...@@ -138,7 +138,7 @@ pub use compiler::backend::aarch64::is_aliased;
pub use compiler::backend::aarch64::get_color_for_precolored; pub use compiler::backend::aarch64::get_color_for_precolored;
/// returns the number of registers in a given RegGroup /// returns the number of registers in a given RegGroup
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub use compiler::backend::aarch64::number_of_regs_in_group; pub use compiler::backend::aarch64::number_of_usable_regs_in_group;
/// returns the number of all machine registers /// returns the number of all machine registers
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub use compiler::backend::aarch64::number_of_all_regs; pub use compiler::backend::aarch64::number_of_all_regs;
......
...@@ -32,6 +32,7 @@ use compiler::backend::reg_alloc::graph_coloring::liveness::Move; ...@@ -32,6 +32,7 @@ use compiler::backend::reg_alloc::graph_coloring::liveness::Move;
use compiler::backend::reg_alloc::graph_coloring::petgraph::graph::NodeIndex; use compiler::backend::reg_alloc::graph_coloring::petgraph::graph::NodeIndex;
const COALESCING : bool = true; const COALESCING : bool = true;
const MAX_REWRITE_ITERATIONS_ALLOWED : usize = 10;
/// GraphColoring algorithm /// GraphColoring algorithm
/// based on Appel's book section 11.4 /// based on Appel's book section 11.4
...@@ -42,15 +43,16 @@ pub struct GraphColoring<'a> { ...@@ -42,15 +43,16 @@ pub struct GraphColoring<'a> {
pub vm: &'a VM, pub vm: &'a VM,
pub ig: InterferenceGraph, pub ig: InterferenceGraph,
/// how many coloring iteration have we done?
/// In case that a bug may trigger the coloring iterate endlessly, we use this count to stop
iteration_count: usize,
/// machine registers, preassigned a color /// machine registers, preassigned a color
precolored: LinkedHashSet<NodeIndex>, precolored: LinkedHashSet<NodeIndex>,
/// all colors available /// all colors available
colors: LinkedHashMap<backend::RegGroup, LinkedHashSet<MuID>>, colors: LinkedHashMap<backend::RegGroup, LinkedHashSet<MuID>>,
/// temporaries, not precolored and not yet processed /// temporaries, not precolored and not yet processed
initial: Vec<NodeIndex>, initial: Vec<NodeIndex>,
/// whether a temp is spillable
// FIXME: not used at the moment
spillable: LinkedHashMap<MuID, bool>,
/// list of low-degree non-move-related nodes /// list of low-degree non-move-related nodes
worklist_simplify: LinkedHashSet<NodeIndex>, worklist_simplify: LinkedHashSet<NodeIndex>,
...@@ -96,14 +98,20 @@ pub struct GraphColoring<'a> { ...@@ -96,14 +98,20 @@ pub struct GraphColoring<'a> {
impl <'a> GraphColoring<'a> { impl <'a> GraphColoring<'a> {
/// starts coloring /// starts coloring
pub fn start (func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> GraphColoring<'a> { pub fn start (func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> GraphColoring<'a> {
GraphColoring::start_with_spill_history(LinkedHashMap::new(), LinkedHashMap::new(), func, cf, vm) GraphColoring::start_with_spill_history(LinkedHashMap::new(), LinkedHashMap::new(), 0, func, cf, vm)
} }
/// restarts coloring with spill history /// restarts coloring with spill history
fn start_with_spill_history(spill_history: LinkedHashMap<MuID, P<Value>>, fn start_with_spill_history(spill_history: LinkedHashMap<MuID, P<Value>>,
spill_scratch_temps: LinkedHashMap<MuID, MuID>, spill_scratch_temps: LinkedHashMap<MuID, MuID>,
iteration_count: usize,
func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> GraphColoring<'a> func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> GraphColoring<'a>
{ {
assert!(iteration_count < MAX_REWRITE_ITERATIONS_ALLOWED,
"reach graph coloring max rewrite iterations ({}), probably something is going wrong",
MAX_REWRITE_ITERATIONS_ALLOWED);
let iteration_count = iteration_count + 1;
trace!("Initializing coloring allocator..."); trace!("Initializing coloring allocator...");
cf.mc().trace_mc(); cf.mc().trace_mc();
...@@ -114,6 +122,7 @@ impl <'a> GraphColoring<'a> { ...@@ -114,6 +122,7 @@ impl <'a> GraphColoring<'a> {
cf: cf, cf: cf,
vm: vm, vm: vm,
ig: ig, ig: ig,
iteration_count: iteration_count,
precolored: LinkedHashSet::new(), precolored: LinkedHashSet::new(),
colors: { colors: {
let mut map = LinkedHashMap::new(); let mut map = LinkedHashMap::new();
...@@ -132,7 +141,6 @@ impl <'a> GraphColoring<'a> { ...@@ -132,7 +141,6 @@ impl <'a> GraphColoring<'a> {
constrained_moves: LinkedHashSet::new(), constrained_moves: LinkedHashSet::new(),
alias: LinkedHashMap::new(), alias: LinkedHashMap::new(),
worklist_spill: Vec::new(), worklist_spill: Vec::new(),
spillable: LinkedHashMap::new(),
spilled_nodes: Vec::new(), spilled_nodes: Vec::new(),
spill_history: spill_history, spill_history: spill_history,
spill_scratch_temps: spill_scratch_temps, spill_scratch_temps: spill_scratch_temps,
...@@ -235,7 +243,7 @@ impl <'a> GraphColoring<'a> { ...@@ -235,7 +243,7 @@ impl <'a> GraphColoring<'a> {
self.rewrite_program(); self.rewrite_program();
// recursively redo graph coloring // recursively redo graph coloring
return GraphColoring::start_with_spill_history(self.spill_history.clone(), self.spill_scratch_temps.clone(), self.func, self.cf, self.vm); return GraphColoring::start_with_spill_history(self.spill_history.clone(), self.spill_scratch_temps.clone(), self.iteration_count, self.func, self.cf, self.vm);
} }
self self
...@@ -282,12 +290,22 @@ impl <'a> GraphColoring<'a> { ...@@ -282,12 +290,22 @@ impl <'a> GraphColoring<'a> {
} }
fn n_regs_for_node(&self, node: NodeIndex) -> usize { fn n_regs_for_node(&self, node: NodeIndex) -> usize {
backend::number_of_regs_in_group(self.ig.get_group_of(node)) backend::number_of_usable_regs_in_group(self.ig.get_group_of(node))
} }
fn is_move_related(&mut self, node: NodeIndex) -> bool { fn is_move_related(&mut self, node: NodeIndex) -> bool {
!self.node_moves(node).is_empty() !self.node_moves(node).is_empty()
} }
fn is_spillable(&self, temp: MuID) -> bool {
// if a temporary is created as scratch temp for a spilled temporary, we
// should not spill it again (infinite loop otherwise)
if self.spill_scratch_temps.contains_key(&temp) {
false
} else {
true
}
}
fn node_moves(&mut self, node: NodeIndex) -> LinkedHashSet<Move> { fn node_moves(&mut self, node: NodeIndex) -> LinkedHashSet<Move> {
let mut moves = LinkedHashSet::new(); let mut moves = LinkedHashSet::new();
...@@ -632,15 +650,7 @@ impl <'a> GraphColoring<'a> { ...@@ -632,15 +650,7 @@ impl <'a> GraphColoring<'a> {
} else if { } else if {
// m is not none // m is not none
let temp = self.ig.get_temp_of(m.unwrap()); let temp = self.ig.get_temp_of(m.unwrap());
let spillable = {match self.spillable.get(&temp) { !self.is_spillable(temp)
None => {
//by default, its spillable
true
},
Some(b) => *b
}};
!spillable
} { } {
m = Some(n); m = Some(n);
} else if (self.ig.get_spill_cost(n) / (self.degree(n) as f32)) } else if (self.ig.get_spill_cost(n) / (self.degree(n) as f32))
......
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