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>" ]
lazy_static = "0.1.15"
log = "0.3.5"
simple_logger = "0.4.0"
nalgebra = "0.8.2"
\ No newline at end of file
nalgebra = "0.8.2"
linked-hash-map = "0.0.10"
\ No newline at end of file
......@@ -5,10 +5,9 @@ use vm::machine_code::CompiledFunction;
use compiler::backend;
use utils::vec_utils;
use utils::hashset_utils;
use utils::LinkedHashSet;
use std::cell::RefCell;
use std::collections::HashSet;
use std::collections::HashMap;
const COALESCING : bool = true;
......@@ -16,8 +15,8 @@ const COALESCING : bool = true;
pub struct GraphColoring {
pub ig: InterferenceGraph,
precolored: HashSet<Node>,
colors: HashMap<backend::RegGroup, HashSet<MuID>>,
precolored: LinkedHashSet<Node>,
colors: HashMap<backend::RegGroup, LinkedHashSet<MuID>>,
pub colored_nodes: Vec<Node>,
initial: Vec<Node>,
......@@ -25,20 +24,20 @@ pub struct GraphColoring {
worklist_moves: Vec<Move>,
movelist: HashMap<Node, RefCell<Vec<Move>>>,
active_moves: HashSet<Move>,
coalesced_nodes: HashSet<Node>,
coalesced_moves: HashSet<Move>,
constrained_moves: HashSet<Move>,
active_moves: LinkedHashSet<Move>,
coalesced_nodes: LinkedHashSet<Node>,
coalesced_moves: LinkedHashSet<Move>,
constrained_moves: LinkedHashSet<Move>,
alias: HashMap<Node, Node>,
worklist_spill: Vec<Node>,
spillable: HashMap<MuID, bool>,
spilled_nodes: Vec<Node>,
worklist_freeze: HashSet<Node>,
frozen_moves: HashSet<Move>,
worklist_freeze: LinkedHashSet<Node>,
frozen_moves: LinkedHashSet<Move>,
worklist_simplify: HashSet<Node>,
worklist_simplify: LinkedHashSet<Node>,
select_stack: Vec<Node>
}
......@@ -47,11 +46,11 @@ impl GraphColoring {
let mut coloring = GraphColoring {
ig: ig,
precolored: HashSet::new(),
precolored: LinkedHashSet::new(),
colors: {
let mut map = HashMap::new();
map.insert(backend::RegGroup::GPR, HashSet::new());
map.insert(backend::RegGroup::FPR, HashSet::new());
map.insert(backend::RegGroup::GPR, LinkedHashSet::new());
map.insert(backend::RegGroup::FPR, LinkedHashSet::new());
map
},
colored_nodes: Vec::new(),
......@@ -61,20 +60,20 @@ impl GraphColoring {
worklist_moves: Vec::new(),
movelist: HashMap::new(),
active_moves: HashSet::new(),
coalesced_nodes: HashSet::new(),
coalesced_moves: HashSet::new(),
constrained_moves: HashSet::new(),
active_moves: LinkedHashSet::new(),
coalesced_nodes: LinkedHashSet::new(),
coalesced_moves: LinkedHashSet::new(),
constrained_moves: LinkedHashSet::new(),
alias: HashMap::new(),
worklist_spill: Vec::new(),
spillable: HashMap::new(),
spilled_nodes: Vec::new(),
worklist_freeze: HashSet::new(),
frozen_moves: HashSet::new(),
worklist_freeze: LinkedHashSet::new(),
frozen_moves: LinkedHashSet::new(),
worklist_simplify: HashSet::new(),
worklist_simplify: LinkedHashSet::new(),
select_stack: Vec::new()
};
......@@ -178,8 +177,8 @@ impl GraphColoring {
!self.node_moves(node).is_empty()
}
fn node_moves(&mut self, node: Node) -> HashSet<Move> {
let mut moves = HashSet::new();
fn node_moves(&mut self, node: Node) -> LinkedHashSet<Move> {
let mut moves = LinkedHashSet::new();
// addAll(active_moves)
for m in self.active_moves.iter() {
......@@ -191,7 +190,7 @@ impl GraphColoring {
moves.insert(m.clone());
}
let mut retained = HashSet::new();
let mut retained = LinkedHashSet::new();
let movelist = &GraphColoring::movelist_mut(&mut self.movelist, node).borrow();
for m in moves.iter() {
if vec_utils::find_value(movelist, *m).is_some() {
......@@ -223,20 +222,21 @@ impl GraphColoring {
fn simplify(&mut self) {
// 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));
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));
self.decrement_degree(m);
}
}
fn adjacent(&self, n: Node) -> HashSet<Node> {
let mut adj = HashSet::new();
fn adjacent(&self, n: Node) -> LinkedHashSet<Node> {
let mut adj = LinkedHashSet::new();
// add n's successors
for s in self.ig.outedges_of(n) {
......@@ -286,9 +286,11 @@ impl GraphColoring {
}
}
fn enable_moves(&mut self, nodes: HashSet<Node>) {
for n in nodes {
for mov in self.node_moves(n) {
fn enable_moves(&mut self, nodes: LinkedHashSet<Node>) {
for n in nodes.iter() {
let n = *n;
for mov in self.node_moves(n).iter() {
let mov = *mov;
if self.active_moves.contains(&mov) {
self.active_moves.insert(mov);
self.worklist_moves.push(mov);
......@@ -373,7 +375,8 @@ impl GraphColoring {
}
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)
|| self.degree(t) < self.n_regs_for_node(t) as isize
|| self.ig.is_adj(t, u) {
......@@ -389,10 +392,14 @@ impl GraphColoring {
let adj_u = self.adjacent(u);
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;
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 {
k += 1;
}
......@@ -426,11 +433,12 @@ impl GraphColoring {
movelist_u.extend_from_slice(movelist_v.as_slice());
}
let mut nodes = HashSet::new();
let mut nodes = LinkedHashSet::new();
nodes.insert(v);
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.decrement_degree(t);
}
......@@ -459,7 +467,7 @@ impl GraphColoring {
fn freeze(&mut self) {
// 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));
self.worklist_simplify.insert(node);
......@@ -467,7 +475,8 @@ impl GraphColoring {
}
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);
if v == self.get_alias(u) {
v = self.get_alias(m.to);
......@@ -528,7 +537,7 @@ impl GraphColoring {
let n = self.select_stack.pop().unwrap();
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) {
let w = self.get_alias(w);
match self.ig.get_color_of(w) {
......@@ -542,7 +551,7 @@ impl GraphColoring {
trace!("{} is a spilled node", self.node_info(n));
self.spilled_nodes.push(n);
} 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);
self.colored_nodes.push(n);
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)]
mod linked_hashset;
pub use utils::linked_hashset::LinkedHashSet;
pub use utils::linked_hashset::LinkedHashMap;
// This porvides some missing operations on Vec.
// They are not included in the standard libarary.
// (because they are likely inefficient?)
......@@ -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 fn replace(s: &mut String, index: usize, replace: &String, replace_len: usize) {
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