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 e0dd25b3 authored by qinsoon's avatar qinsoon
Browse files

spill heuristics with consideration of loop depth

parent 9be20de9
...@@ -86,10 +86,10 @@ impl CompilerPass for MCLoopAnalysis { ...@@ -86,10 +86,10 @@ impl CompilerPass for MCLoopAnalysis {
#[allow(dead_code)] #[allow(dead_code)]
pub struct MCLoopAnalysisResult { pub struct MCLoopAnalysisResult {
domtree: MCDomTree, pub domtree: MCDomTree,
loops: LinkedRepeatableMultiMap<MuName, MCNaturalLoop>, pub loops: LinkedRepeatableMultiMap<MuName, MCNaturalLoop>,
loop_nest_tree: MCLoopNestTree, pub loop_nest_tree: MCLoopNestTree,
loop_depth: LinkedHashMap<MuName, usize> pub loop_depth: LinkedHashMap<MuName, usize>
} }
impl MCLoopAnalysis { impl MCLoopAnalysis {
...@@ -238,7 +238,7 @@ fn compute_domtree(entry: MuName, idoms: &LinkedHashMap<MuName, MuName>) -> MCDo ...@@ -238,7 +238,7 @@ fn compute_domtree(entry: MuName, idoms: &LinkedHashMap<MuName, MuName>) -> MCDo
} }
#[derive(Debug)] #[derive(Debug)]
struct MCNaturalLoop { pub struct MCNaturalLoop {
header: MuName, header: MuName,
backedge: MuName, backedge: MuName,
blocks: LinkedHashSet<MuName> blocks: LinkedHashSet<MuName>
......
...@@ -874,10 +874,10 @@ impl<'a> GraphColoring<'a> { ...@@ -874,10 +874,10 @@ impl<'a> GraphColoring<'a> {
m = Some(n); m = Some(n);
} else { } else {
let cur_m = m.unwrap(); let cur_m = m.unwrap();
let ratio_m = self.ig.get_spill_cost(cur_m) / (self.ig.get_degree_of(cur_m) as f32); let cost_m = self.ig.get_spill_cost(cur_m);
let ratio_n = self.ig.get_spill_cost(n) / (self.ig.get_degree_of(n) as f32); let cost_n = self.ig.get_spill_cost(n);
if ratio_n < ratio_m { if cost_n < cost_m {
trace!("{} is preferred: ({} < {})", n, ratio_n, ratio_m); trace!("{} is preferred: ({} < {})", n, cost_n, cost_m);
m = Some(n); m = Some(n);
} }
} }
......
...@@ -21,6 +21,14 @@ use utils::LinkedHashSet; ...@@ -21,6 +21,14 @@ use utils::LinkedHashSet;
use utils::LinkedHashMap; use utils::LinkedHashMap;
use std::fmt; use std::fmt;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum NodeType {
Def,
Use,
Copy,
Machine
}
/// GraphNode represents a node in the interference graph. /// GraphNode represents a node in the interference graph.
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub struct Node { pub struct Node {
...@@ -120,7 +128,13 @@ impl InterferenceGraph { ...@@ -120,7 +128,13 @@ impl InterferenceGraph {
/// creates a new node for a temp (if we already created a temp for the temp, returns the node) /// creates a new node for a temp (if we already created a temp for the temp, returns the node)
/// This function will increase spill cost for the node by 1 each tiem it is called for the temp /// This function will increase spill cost for the node by 1 each tiem it is called for the temp
fn new_node(&mut self, reg_id: MuID, context: &FunctionContext) -> MuID { fn new_node(
&mut self,
reg_id: MuID,
ty: NodeType,
loop_depth: usize,
context: &FunctionContext
) -> MuID {
let entry = context.get_value(reg_id).unwrap(); let entry = context.get_value(reg_id).unwrap();
// if it is the first time, create the node // if it is the first time, create the node
...@@ -140,11 +154,26 @@ impl InterferenceGraph { ...@@ -140,11 +154,26 @@ impl InterferenceGraph {
// get node // get node
let node_mut = self.nodes.get_mut(&reg_id).unwrap(); let node_mut = self.nodes.get_mut(&reg_id).unwrap();
// increase node spill cost // increase node spill cost
node_mut.spill_cost += 1.0f32; node_mut.spill_cost += InterferenceGraph::spillcost_heuristic(ty, loop_depth);
reg_id reg_id
} }
fn spillcost_heuristic(ty: NodeType, loop_depth: usize) -> f32 {
const DEF_WEIGHT: f32 = 1f32;
const USE_WEIGHT: f32 = 1f32;
const COPY_WEIGHT: f32 = 0.5f32;
let loop_depth = loop_depth as i32;
match ty {
NodeType::Machine => 0f32,
NodeType::Def => DEF_WEIGHT * (10f32.powi(loop_depth)),
NodeType::Use => USE_WEIGHT * (10f32.powi(loop_depth)),
NodeType::Copy => COPY_WEIGHT * (10f32.powi(loop_depth))
}
}
/// returns all the nodes in the graph /// returns all the nodes in the graph
pub fn nodes(&self) -> Vec<MuID> { pub fn nodes(&self) -> Vec<MuID> {
self.nodes.keys().map(|x| *x).collect() self.nodes.keys().map(|x| *x).collect()
...@@ -327,6 +356,8 @@ pub fn build_interference_graph_chaitin_briggs( ...@@ -327,6 +356,8 @@ pub fn build_interference_graph_chaitin_briggs(
cf: &mut CompiledFunction, cf: &mut CompiledFunction,
func: &MuFunctionVersion func: &MuFunctionVersion
) -> InterferenceGraph { ) -> InterferenceGraph {
use compiler::backend::reg_alloc::graph_coloring::liveness::NodeType::*;
let _p = hprof::enter("regalloc: build global liveness"); let _p = hprof::enter("regalloc: build global liveness");
build_global_liveness(cf, func); build_global_liveness(cf, func);
drop(_p); drop(_p);
...@@ -339,22 +370,47 @@ pub fn build_interference_graph_chaitin_briggs( ...@@ -339,22 +370,47 @@ pub fn build_interference_graph_chaitin_briggs(
// precolor machine register nodes // precolor machine register nodes
for reg in backend::all_regs().values() { for reg in backend::all_regs().values() {
let reg_id = c(reg.extract_ssa_id().unwrap()); let reg_id = c(reg.extract_ssa_id().unwrap());
let node = ig.new_node(reg_id, &func.context); let node = ig.new_node(reg_id, Machine, 0, &func.context);
let precolor = backend::get_color_for_precolored(reg_id); let precolor = backend::get_color_for_precolored(reg_id);
ig.color_node(node, precolor); ig.color_node(node, precolor);
} }
// initialize and creates nodes for all the involved temps/regs // initialize and creates nodes for all the involved temps/regs
for i in 0..cf.mc().number_of_insts() { let mc = cf.mc();
for reg_id in cf.mc().get_inst_reg_defines(i) { for block in mc.get_all_blocks() {
let reg_id = c(reg_id); debug!("build graph node for block {}", block);
ig.new_node(reg_id, &func.context); let loop_depth: usize = match cf.loop_analysis.as_ref().unwrap().loop_depth.get(&block) {
} Some(depth) => *depth,
None => 0
};
debug!("loop depth = {}", loop_depth);
for i in mc.get_block_range(&block).unwrap() {
// we separate the case of move nodes, and normal instruction
// as they yield different spill cost
// (we prefer spill a node in move instruction
// as the move instruction can be eliminated)
if mc.is_move(i) {
for reg_id in mc.get_inst_reg_defines(i) {
let reg_id = c(reg_id);
ig.new_node(reg_id, Copy, loop_depth, &func.context);
}
for reg_id in cf.mc().get_inst_reg_uses(i) { for reg_id in mc.get_inst_reg_uses(i) {
let reg_id = c(reg_id); let reg_id = c(reg_id);
ig.new_node(reg_id, &func.context); ig.new_node(reg_id, Copy, loop_depth, &func.context);
}
} else {
for reg_id in mc.get_inst_reg_defines(i) {
let reg_id = c(reg_id);
ig.new_node(reg_id, Def, loop_depth, &func.context);
}
for reg_id in mc.get_inst_reg_uses(i) {
let reg_id = c(reg_id);
ig.new_node(reg_id, Use, loop_depth, &func.context);
}
}
} }
} }
......
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