Commit eeaecb3f authored by qinsoon's avatar qinsoon

Replacing HashSet with LinkedHashSet so that results from regalloc are fixed

parent 30a6d074
...@@ -8,4 +8,5 @@ authors = [ "Your name <you@example.com>" ] ...@@ -8,4 +8,5 @@ authors = [ "Your name <you@example.com>" ]
lazy_static = "0.1.15" lazy_static = "0.1.15"
log = "0.3.5" log = "0.3.5"
simple_logger = "0.4.0" simple_logger = "0.4.0"
nalgebra = "0.8.2" nalgebra = "0.8.2"
\ No newline at end of file linked-hash-map = "0.0.10"
\ No newline at end of file
...@@ -5,10 +5,9 @@ use vm::machine_code::CompiledFunction; ...@@ -5,10 +5,9 @@ use vm::machine_code::CompiledFunction;
use compiler::backend; use compiler::backend;
use utils::vec_utils; use utils::vec_utils;
use utils::hashset_utils; use utils::LinkedHashSet;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashSet;
use std::collections::HashMap; use std::collections::HashMap;
const COALESCING : bool = true; const COALESCING : bool = true;
...@@ -16,8 +15,8 @@ const COALESCING : bool = true; ...@@ -16,8 +15,8 @@ const COALESCING : bool = true;
pub struct GraphColoring { pub struct GraphColoring {
pub ig: InterferenceGraph, pub ig: InterferenceGraph,
precolored: HashSet<Node>, precolored: LinkedHashSet<Node>,
colors: HashMap<backend::RegGroup, HashSet<MuID>>, colors: HashMap<backend::RegGroup, LinkedHashSet<MuID>>,
pub colored_nodes: Vec<Node>, pub colored_nodes: Vec<Node>,
initial: Vec<Node>, initial: Vec<Node>,
...@@ -25,20 +24,20 @@ pub struct GraphColoring { ...@@ -25,20 +24,20 @@ pub struct GraphColoring {
worklist_moves: Vec<Move>, worklist_moves: Vec<Move>,
movelist: HashMap<Node, RefCell<Vec<Move>>>, movelist: HashMap<Node, RefCell<Vec<Move>>>,
active_moves: HashSet<Move>, active_moves: LinkedHashSet<Move>,
coalesced_nodes: HashSet<Node>, coalesced_nodes: LinkedHashSet<Node>,
coalesced_moves: HashSet<Move>, coalesced_moves: LinkedHashSet<Move>,
constrained_moves: HashSet<Move>, constrained_moves: LinkedHashSet<Move>,
alias: HashMap<Node, Node>, alias: HashMap<Node, Node>,
worklist_spill: Vec<Node>, worklist_spill: Vec<Node>,
spillable: HashMap<MuID, bool>, spillable: HashMap<MuID, bool>,
spilled_nodes: Vec<Node>, spilled_nodes: Vec<Node>,
worklist_freeze: HashSet<Node>, worklist_freeze: LinkedHashSet<Node>,
frozen_moves: HashSet<Move>, frozen_moves: LinkedHashSet<Move>,
worklist_simplify: HashSet<Node>, worklist_simplify: LinkedHashSet<Node>,
select_stack: Vec<Node> select_stack: Vec<Node>
} }
...@@ -47,11 +46,11 @@ impl GraphColoring { ...@@ -47,11 +46,11 @@ impl GraphColoring {
let mut coloring = GraphColoring { let mut coloring = GraphColoring {
ig: ig, ig: ig,
precolored: HashSet::new(), precolored: LinkedHashSet::new(),
colors: { colors: {
let mut map = HashMap::new(); let mut map = HashMap::new();
map.insert(backend::RegGroup::GPR, HashSet::new()); map.insert(backend::RegGroup::GPR, LinkedHashSet::new());
map.insert(backend::RegGroup::FPR, HashSet::new()); map.insert(backend::RegGroup::FPR, LinkedHashSet::new());
map map
}, },
colored_nodes: Vec::new(), colored_nodes: Vec::new(),
...@@ -61,20 +60,20 @@ impl GraphColoring { ...@@ -61,20 +60,20 @@ impl GraphColoring {
worklist_moves: Vec::new(), worklist_moves: Vec::new(),
movelist: HashMap::new(), movelist: HashMap::new(),
active_moves: HashSet::new(), active_moves: LinkedHashSet::new(),
coalesced_nodes: HashSet::new(), coalesced_nodes: LinkedHashSet::new(),
coalesced_moves: HashSet::new(), coalesced_moves: LinkedHashSet::new(),
constrained_moves: HashSet::new(), constrained_moves: LinkedHashSet::new(),
alias: HashMap::new(), alias: HashMap::new(),
worklist_spill: Vec::new(), worklist_spill: Vec::new(),
spillable: HashMap::new(), spillable: HashMap::new(),
spilled_nodes: Vec::new(), spilled_nodes: Vec::new(),
worklist_freeze: HashSet::new(), worklist_freeze: LinkedHashSet::new(),
frozen_moves: HashSet::new(), frozen_moves: LinkedHashSet::new(),
worklist_simplify: HashSet::new(), worklist_simplify: LinkedHashSet::new(),
select_stack: Vec::new() select_stack: Vec::new()
}; };
...@@ -178,8 +177,8 @@ impl GraphColoring { ...@@ -178,8 +177,8 @@ impl GraphColoring {
!self.node_moves(node).is_empty() !self.node_moves(node).is_empty()
} }
fn node_moves(&mut self, node: Node) -> HashSet<Move> { fn node_moves(&mut self, node: Node) -> LinkedHashSet<Move> {
let mut moves = HashSet::new(); let mut moves = LinkedHashSet::new();
// addAll(active_moves) // addAll(active_moves)
for m in self.active_moves.iter() { for m in self.active_moves.iter() {
...@@ -191,7 +190,7 @@ impl GraphColoring { ...@@ -191,7 +190,7 @@ impl GraphColoring {
moves.insert(m.clone()); moves.insert(m.clone());
} }
let mut retained = HashSet::new(); let mut retained = LinkedHashSet::new();
let movelist = &GraphColoring::movelist_mut(&mut self.movelist, node).borrow(); let movelist = &GraphColoring::movelist_mut(&mut self.movelist, node).borrow();
for m in moves.iter() { for m in moves.iter() {
if vec_utils::find_value(movelist, *m).is_some() { if vec_utils::find_value(movelist, *m).is_some() {
...@@ -223,20 +222,21 @@ impl GraphColoring { ...@@ -223,20 +222,21 @@ impl GraphColoring {
fn simplify(&mut self) { fn simplify(&mut self) {
// remove next element from worklist_simplify, we know its not empty // remove next element from worklist_simplify, we know its not empty
let node = hashset_utils::pop_first(&mut self.worklist_simplify).unwrap(); let node = self.worklist_simplify.pop_front().unwrap();
trace!("Simplifying {}", self.node_info(node)); trace!("Simplifying {}", self.node_info(node));
self.select_stack.push(node); self.select_stack.push(node);
for m in self.adjacent(node) { for m in self.adjacent(node).iter() {
let m = *m;
trace!("decrement degree of its adjacent node {}", self.node_info(m)); trace!("decrement degree of its adjacent node {}", self.node_info(m));
self.decrement_degree(m); self.decrement_degree(m);
} }
} }
fn adjacent(&self, n: Node) -> HashSet<Node> { fn adjacent(&self, n: Node) -> LinkedHashSet<Node> {
let mut adj = HashSet::new(); let mut adj = LinkedHashSet::new();
// add n's successors // add n's successors
for s in self.ig.outedges_of(n) { for s in self.ig.outedges_of(n) {
...@@ -286,9 +286,11 @@ impl GraphColoring { ...@@ -286,9 +286,11 @@ impl GraphColoring {
} }
} }
fn enable_moves(&mut self, nodes: HashSet<Node>) { fn enable_moves(&mut self, nodes: LinkedHashSet<Node>) {
for n in nodes { for n in nodes.iter() {
for mov in self.node_moves(n) { let n = *n;
for mov in self.node_moves(n).iter() {
let mov = *mov;
if self.active_moves.contains(&mov) { if self.active_moves.contains(&mov) {
self.active_moves.insert(mov); self.active_moves.insert(mov);
self.worklist_moves.push(mov); self.worklist_moves.push(mov);
...@@ -373,7 +375,8 @@ impl GraphColoring { ...@@ -373,7 +375,8 @@ impl GraphColoring {
} }
fn ok(&self, u: Node, v: Node) -> bool { fn ok(&self, u: Node, v: Node) -> bool {
for t in self.adjacent(v) { for t in self.adjacent(v).iter() {
let t = *t;
if !self.precolored.contains(&t) if !self.precolored.contains(&t)
|| self.degree(t) < self.n_regs_for_node(t) as isize || self.degree(t) < self.n_regs_for_node(t) as isize
|| self.ig.is_adj(t, u) { || self.ig.is_adj(t, u) {
...@@ -389,10 +392,14 @@ impl GraphColoring { ...@@ -389,10 +392,14 @@ impl GraphColoring {
let adj_u = self.adjacent(u); let adj_u = self.adjacent(u);
let adj_v = self.adjacent(v); let adj_v = self.adjacent(v);
let nodes = adj_u.union(&adj_v).collect::<HashSet<_>>(); let nodes = {
let mut ret = adj_u;
ret.add_all(adj_v);
ret
};
let mut k = 0; let mut k = 0;
for n in nodes { for n in nodes.iter() {
if self.precolored.contains(n) || self.degree(*n) >= self.n_regs_for_node(*n) as isize { if self.precolored.contains(n) || self.degree(*n) >= self.n_regs_for_node(*n) as isize {
k += 1; k += 1;
} }
...@@ -426,11 +433,12 @@ impl GraphColoring { ...@@ -426,11 +433,12 @@ impl GraphColoring {
movelist_u.extend_from_slice(movelist_v.as_slice()); movelist_u.extend_from_slice(movelist_v.as_slice());
} }
let mut nodes = HashSet::new(); let mut nodes = LinkedHashSet::new();
nodes.insert(v); nodes.insert(v);
self.enable_moves(nodes); self.enable_moves(nodes);
for t in self.adjacent(v) { for t in self.adjacent(v).iter() {
let t = *t;
self.add_edge(t, u); self.add_edge(t, u);
self.decrement_degree(t); self.decrement_degree(t);
} }
...@@ -459,7 +467,7 @@ impl GraphColoring { ...@@ -459,7 +467,7 @@ impl GraphColoring {
fn freeze(&mut self) { fn freeze(&mut self) {
// it is not empty (checked before) // it is not empty (checked before)
let node = hashset_utils::pop_first(&mut self.worklist_freeze).unwrap(); let node = self.worklist_freeze.pop_front().unwrap();
trace!("Freezing {}...", self.node_info(node)); trace!("Freezing {}...", self.node_info(node));
self.worklist_simplify.insert(node); self.worklist_simplify.insert(node);
...@@ -467,7 +475,8 @@ impl GraphColoring { ...@@ -467,7 +475,8 @@ impl GraphColoring {
} }
fn freeze_moves(&mut self, u: Node) { fn freeze_moves(&mut self, u: Node) {
for m in self.node_moves(u) { for m in self.node_moves(u).iter() {
let m = *m;
let mut v = self.get_alias(m.from); let mut v = self.get_alias(m.from);
if v == self.get_alias(u) { if v == self.get_alias(u) {
v = self.get_alias(m.to); v = self.get_alias(m.to);
...@@ -528,7 +537,7 @@ impl GraphColoring { ...@@ -528,7 +537,7 @@ impl GraphColoring {
let n = self.select_stack.pop().unwrap(); let n = self.select_stack.pop().unwrap();
trace!("Assigning color to {}", self.node_info(n)); trace!("Assigning color to {}", self.node_info(n));
let mut ok_colors = self.colors.get(&self.ig.get_group_of(n)).unwrap().clone(); let mut ok_colors : LinkedHashSet<MuID> = self.colors.get(&self.ig.get_group_of(n)).unwrap().clone();
for w in self.ig.outedges_of(n) { for w in self.ig.outedges_of(n) {
let w = self.get_alias(w); let w = self.get_alias(w);
match self.ig.get_color_of(w) { match self.ig.get_color_of(w) {
...@@ -542,7 +551,7 @@ impl GraphColoring { ...@@ -542,7 +551,7 @@ impl GraphColoring {
trace!("{} is a spilled node", self.node_info(n)); trace!("{} is a spilled node", self.node_info(n));
self.spilled_nodes.push(n); self.spilled_nodes.push(n);
} else { } else {
let first_available_color = hashset_utils::pop_first(&mut ok_colors).unwrap(); let first_available_color = ok_colors.pop_front().unwrap();
trace!("Color {} as {}", self.node_info(n), first_available_color); trace!("Color {} as {}", self.node_info(n), first_available_color);
self.colored_nodes.push(n); self.colored_nodes.push(n);
self.ig.color_node(n, first_available_color); self.ig.color_node(n, first_available_color);
......
extern crate linked_hash_map;
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash};
use std::borrow::Borrow;
use self::linked_hash_map::Keys;
pub use self::linked_hash_map::LinkedHashMap;
pub struct LinkedHashSet<K, S = RandomState>(LinkedHashMap<K, (), S>);
impl<K: Hash + Eq> LinkedHashSet<K> {
pub fn new() -> Self {
LinkedHashSet(LinkedHashMap::new())
}
}
impl<K: Hash + Eq, S: BuildHasher> LinkedHashSet<K, S> {
pub fn insert(&mut self, k: K) -> Option<()> {
self.0.insert(k, ())
}
pub fn contains<Q: ?Sized>(&self, k: &Q) -> bool
where K: Borrow<Q>,
Q: Eq + Hash
{
self.0.contains_key(k)
}
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<()>
where K: Borrow<Q>,
Q: Eq + Hash
{
self.0.remove(k)
}
pub fn iter(&self) -> Keys<K, ()> {
self.0.keys()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn pop_front(&mut self) -> Option<K> {
match self.0.pop_front() {
Some((k, _)) => Some(k),
None => None
}
}
pub fn add_all(&mut self, mut other: Self) {
while !other.is_empty() {
let entry = other.pop_front().unwrap();
self.insert(entry);
}
}
}
impl<K: Hash + Eq + Clone> Clone for LinkedHashSet<K> {
fn clone(&self) -> Self {
LinkedHashSet(self.0.clone())
}
}
use std::fmt;
use std::fmt::DebugSet;
impl<A: fmt::Debug + Hash + Eq, S: BuildHasher> fmt::Debug for LinkedHashSet<A, S> {
/// Returns a string that lists the key-value pairs in insertion order.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
\ No newline at end of file
#![allow(dead_code)] #![allow(dead_code)]
mod linked_hashset;
pub use utils::linked_hashset::LinkedHashSet;
pub use utils::linked_hashset::LinkedHashMap;
// This porvides some missing operations on Vec. // This porvides some missing operations on Vec.
// They are not included in the standard libarary. // They are not included in the standard libarary.
// (because they are likely inefficient?) // (because they are likely inefficient?)
...@@ -35,20 +39,6 @@ pub mod vec_utils { ...@@ -35,20 +39,6 @@ pub mod vec_utils {
} }
} }
pub mod hashset_utils {
use std::collections::HashSet;
use std::hash::Hash;
pub fn pop_first<T: Eq + Hash + Copy> (set: &mut HashSet<T>) -> Option<T> {
if set.is_empty() {
None
} else {
let next : T = set.iter().next().unwrap().clone();
set.take(&next)
}
}
}
pub mod string_utils { pub mod string_utils {
pub fn replace(s: &mut String, index: usize, replace: &String, replace_len: usize) { pub fn replace(s: &mut String, index: usize, replace: &String, replace_len: usize) {
let vec = unsafe {s.as_mut_vec()}; let vec = unsafe {s.as_mut_vec()};
......
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