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 {
#[allow(dead_code)]
pub struct MCLoopAnalysisResult {
domtree: MCDomTree,
loops: LinkedRepeatableMultiMap<MuName, MCNaturalLoop>,
loop_nest_tree: MCLoopNestTree,
loop_depth: LinkedHashMap<MuName, usize>
pub domtree: MCDomTree,
pub loops: LinkedRepeatableMultiMap<MuName, MCNaturalLoop>,
pub loop_nest_tree: MCLoopNestTree,
pub loop_depth: LinkedHashMap<MuName, usize>
}
impl MCLoopAnalysis {
......@@ -238,7 +238,7 @@ fn compute_domtree(entry: MuName, idoms: &LinkedHashMap<MuName, MuName>) -> MCDo
}
#[derive(Debug)]
struct MCNaturalLoop {
pub struct MCNaturalLoop {
header: MuName,
backedge: MuName,
blocks: LinkedHashSet<MuName>
......
......@@ -874,10 +874,10 @@ impl<'a> GraphColoring<'a> {
m = Some(n);
} else {
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 ratio_n = self.ig.get_spill_cost(n) / (self.ig.get_degree_of(n) as f32);
if ratio_n < ratio_m {
trace!("{} is preferred: ({} < {})", n, ratio_n, ratio_m);
let cost_m = self.ig.get_spill_cost(cur_m);
let cost_n = self.ig.get_spill_cost(n);
if cost_n < cost_m {
trace!("{} is preferred: ({} < {})", n, cost_n, cost_m);
m = Some(n);
}
}
......
......@@ -21,6 +21,14 @@ use utils::LinkedHashSet;
use utils::LinkedHashMap;
use std::fmt;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum NodeType {
Def,
Use,
Copy,
Machine
}
/// GraphNode represents a node in the interference graph.
#[derive(Clone, Copy, PartialEq)]
pub struct Node {
......@@ -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)
/// 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();
// if it is the first time, create the node
......@@ -140,11 +154,26 @@ impl InterferenceGraph {
// get node
let node_mut = self.nodes.get_mut(&reg_id).unwrap();
// increase node spill cost
node_mut.spill_cost += 1.0f32;
node_mut.spill_cost += InterferenceGraph::spillcost_heuristic(ty, loop_depth);
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
pub fn nodes(&self) -> Vec<MuID> {
self.nodes.keys().map(|x| *x).collect()
......@@ -327,6 +356,8 @@ pub fn build_interference_graph_chaitin_briggs(
cf: &mut CompiledFunction,
func: &MuFunctionVersion
) -> InterferenceGraph {
use compiler::backend::reg_alloc::graph_coloring::liveness::NodeType::*;
let _p = hprof::enter("regalloc: build global liveness");
build_global_liveness(cf, func);
drop(_p);
......@@ -339,22 +370,47 @@ pub fn build_interference_graph_chaitin_briggs(
// precolor machine register nodes
for reg in backend::all_regs().values() {
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);
ig.color_node(node, precolor);
}
// initialize and creates nodes for all the involved temps/regs
for i in 0..cf.mc().number_of_insts() {
for reg_id in cf.mc().get_inst_reg_defines(i) {
let mc = cf.mc();
for block in mc.get_all_blocks() {
debug!("build graph node for block {}", block);
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, &func.context);
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);
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