GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

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