Commit 8423d198 authored by qinsoon's avatar qinsoon

[wip] coalesce (untested)

parent dd776b84
......@@ -6,6 +6,7 @@ use vm::machine_code::CompiledFunction;
use compiler::backend;
use utils::vec_utils;
use std::cell::RefCell;
use std::collections::HashSet;
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
......@@ -23,9 +24,11 @@ pub struct GraphColoring <'a> {
degree: HashMap<Node, usize>,
worklist_moves: Vec<Move>,
movelist: HashMap<Node, Vec<Move>>,
movelist: HashMap<Node, RefCell<Vec<Move>>>,
active_moves: HashSet<Move>,
coalesced_nodes: HashSet<Node>,
coalesced_moves: HashSet<Move>,
alias: HashMap<Node, Node>,
worklist_spill: Vec<Node>,
worklist_freeze: HashSet<Node>,
......@@ -50,6 +53,8 @@ impl <'a> GraphColoring <'a> {
movelist: HashMap::new(),
active_moves: HashSet::new(),
coalesced_nodes: HashSet::new(),
coalesced_moves: HashSet::new(),
alias: HashMap::new(),
worklist_spill: Vec::new(),
worklist_freeze: HashSet::new(),
......@@ -108,8 +113,8 @@ impl <'a> GraphColoring <'a> {
let ref mut movelist = self.movelist;
for m in ig.moves() {
self.worklist_moves.push(m.clone());
GraphColoring::movelist_mut(movelist, m.from).push(m.clone());
GraphColoring::movelist_mut(movelist, m.to).push(m.clone());
GraphColoring::movelist_mut(movelist, m.from).borrow_mut().push(m.clone());
GraphColoring::movelist_mut(movelist, m.to).borrow_mut().push(m.clone());
}
}
}
......@@ -156,7 +161,7 @@ impl <'a> GraphColoring <'a> {
}
let mut retained = HashSet::new();
let movelist = GraphColoring::movelist_mut(&mut self.movelist, node);
let movelist = &GraphColoring::movelist_mut(&mut self.movelist, node).borrow();
for m in moves.iter() {
if vec_utils::find_value(movelist, *m).is_some() {
retained.insert(*m);
......@@ -166,12 +171,23 @@ impl <'a> GraphColoring <'a> {
retained
}
fn movelist_mut(list: &mut HashMap<Node, Vec<Move>>, node: Node) -> &mut Vec<Move> {
// avoid using &mut self as argument
// in build(), we will need to mutate on self.movelist while
// holding an immmutable reference of self(self.ig)
fn movelist_mut(list: &mut HashMap<Node, RefCell<Vec<Move>>>, node: Node) -> &RefCell<Vec<Move>> {
GraphColoring::movelist_check(list, node);
unsafe {GraphColoring::movelist_nocheck(list, node)}
}
fn movelist_check(list: &mut HashMap<Node, RefCell<Vec<Move>>>, node: Node) {
if !list.contains_key(&node) {
list.insert(node, Vec::new());
list.insert(node, RefCell::new(Vec::new()));
}
list.get_mut(&node).unwrap()
}
// allows getting the Vec<Move> without a mutable reference of the hashmap
unsafe fn movelist_nocheck(list: &HashMap<Node, RefCell<Vec<Move>>>, node: Node) -> &RefCell<Vec<Move>> {
list.get(&node).unwrap()
}
fn simplify(&mut self) {
......@@ -188,7 +204,7 @@ impl <'a> GraphColoring <'a> {
}
}
fn adjacent(&mut self, n: Node) -> HashSet<Node> {
fn adjacent(&self, n: Node) -> HashSet<Node> {
let mut adj = HashSet::new();
// add n's successors
......@@ -247,7 +263,152 @@ impl <'a> GraphColoring <'a> {
}
fn coalesce(&mut self) {
unimplemented!()
let m = self.worklist_moves.pop().unwrap();
let x = self.get_alias(m.from);
let y = self.get_alias(m.to);
let (u, v, precolored_u, precolored_v) = {
if self.precolored.contains(&y) {
let u = y;
let v = x;
let precolored_u = true;
let precolored_v = self.precolored.contains(&v);
(u, v, precolored_u, precolored_v)
} else {
let u = x;
let v = y;
let precolored_u = self.precolored.contains(&u);
let precolored_v = self.precolored.contains(&v);
(u, v, precolored_u, precolored_v)
}
};
if u == v {
self.coalesced_moves.insert(m);
if !precolored_u {
self.add_worklist(u);
}
} else if precolored_v || self.ig.is_adj(u, v) {
self.coalesced_moves.insert(m);
if !precolored_u {
self.add_worklist(u);
}
if !precolored_v {
self.add_worklist(v);
}
} else if (precolored_u && self.ok(u, v))
|| (!precolored_u && self.conservative(u, v)) {
self.coalesced_moves.insert(m);
self.combine(u, v);
if !precolored_u {
self.add_worklist(u);
}
} else {
self.active_moves.insert(m);
}
}
fn get_alias(&self, node: Node) -> Node {
if self.coalesced_nodes.contains(&node) {
self.get_alias(*self.alias.get(&node).unwrap())
} else {
node
}
}
fn add_worklist(&mut self, node: Node) {
if !self.is_move_related(node) && self.degree(node) < self.n_regs_for_node(node) {
self.worklist_freeze.remove(&node);
self.worklist_simplify.insert(node);
}
}
fn ok(&self, u: Node, v: Node) -> bool {
for t in self.adjacent(v) {
if !self.precolored.contains(&t)
|| self.degree(t) < self.n_regs_for_node(t)
|| self.ig.is_adj(t, u) {
return false;
}
}
true
}
fn conservative(&self, u: Node, v: Node) -> bool {
debug_assert!(self.ig.get_group_of(u) == self.ig.get_group_of(v));
let adj_u = self.adjacent(u);
let adj_v = self.adjacent(v);
let nodes = adj_u.union(&adj_v).collect::<HashSet<_>>();
let mut k = 0;
for n in nodes {
if self.precolored.contains(n) || self.degree(*n) >= self.n_regs_for_node(*n) {
k += 1;
}
}
k < self.n_regs_for_node(u)
}
fn combine(&mut self, u: Node, v: Node) {
if self.worklist_freeze.contains(&v) {
self.worklist_freeze.remove(&v);
self.coalesced_nodes.insert(v);
} else {
vec_utils::remove_value(&mut self.worklist_spill, v);
self.coalesced_nodes.insert(v);
}
self.alias.insert(v, u);
{
let ref mut movelist = self.movelist;
GraphColoring::movelist_check(movelist, u);
GraphColoring::movelist_check(movelist, v);
// we checked before getting the movelist, its safe
// use nocheck version which requires only immutable references of movelist
// avoid maintaining a mutable reference of movelist alive
let movelist_u = &mut unsafe {GraphColoring::movelist_nocheck(movelist, u)}.borrow_mut();
let movelist_v = &mut unsafe {GraphColoring::movelist_nocheck(movelist, v)}.borrow_mut();
// addAll()
movelist_u.extend_from_slice(movelist_v.as_slice());
}
let mut nodes = HashSet::new();
nodes.insert(v);
self.enable_moves(nodes);
for t in self.adjacent(v) {
self.add_edge(t, u);
self.decrement_degree(t);
}
if self.worklist_freeze.contains(&u)
&& self.degree(u) >= self.n_regs_for_node(u) {
self.worklist_freeze.remove(&u);
self.worklist_spill.push(u);
}
}
fn add_edge(&mut self, u: Node, v: Node) {
if u != v && !self.ig.is_adj(u, v) {
if !self.precolored.contains(&u) {
self.ig.add_interference_edge(u, v);
let degree_u = self.degree(u);
self.degree.insert(u, degree_u + 1);
}
if !self.precolored.contains(&v) {
self.ig.add_interference_edge(v, u);
let degree_v = self.degree(v);
self.degree.insert(v, degree_v + 1);
}
}
}
fn freeze(&mut self) {
......
......@@ -108,7 +108,7 @@ impl InterferenceGraph {
self.moves.insert(Move{from: src, to: dst});
}
fn add_interference_edge(&mut self, from: Node, to: Node) {
pub fn add_interference_edge(&mut self, from: Node, to: Node) {
// only if two nodes are from the same RegGroup,
// they may interefere
if self.nodes_property.get(&from).unwrap().group
......@@ -133,7 +133,7 @@ impl InterferenceGraph {
node1 == node2
}
fn is_adj(&self, from: Node, to: Node) -> bool {
pub fn is_adj(&self, from: Node, to: Node) -> bool {
let ref matrix = self.matrix.as_ref().unwrap();
matrix[(from.0, to.0)] || matrix[(to.0, from.0)]
......
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