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.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.2% of users enabled 2FA.

Commit 4969b45f authored by qinsoon's avatar qinsoon
Browse files

use petgraph::Graph for coloring reg alloc

was using nalgebra::DMatrix to implement a graph
parent d1eba234
...@@ -25,11 +25,11 @@ libloading = "0.3" ...@@ -25,11 +25,11 @@ libloading = "0.3"
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"
hprof = "0.1.3" hprof = "0.1.3"
memmap = "0.4.0" memmap = "0.4.0"
memsec = "0.1.9" memsec = "0.1.9"
rustc-serialize = "*" rustc-serialize = "*"
time = "0.1.34" time = "0.1.34"
maplit = "0.1.4" maplit = "0.1.4"
docopt = "0.6" docopt = "0.6"
\ No newline at end of file petgraph = "0.4.1"
\ No newline at end of file
...@@ -2,7 +2,6 @@ use ast::ir::*; ...@@ -2,7 +2,6 @@ use ast::ir::*;
use compiler::backend; use compiler::backend;
use compiler::backend::reg_alloc::graph_coloring; use compiler::backend::reg_alloc::graph_coloring;
use compiler::backend::reg_alloc::graph_coloring::liveness::InterferenceGraph; use compiler::backend::reg_alloc::graph_coloring::liveness::InterferenceGraph;
use compiler::backend::reg_alloc::graph_coloring::liveness::{Node, Move};
use compiler::machine_code::CompiledFunction; use compiler::machine_code::CompiledFunction;
use vm::VM; use vm::VM;
...@@ -12,6 +11,9 @@ use utils::LinkedHashSet; ...@@ -12,6 +11,9 @@ use utils::LinkedHashSet;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use compiler::backend::reg_alloc::graph_coloring::liveness::Move;
use compiler::backend::reg_alloc::graph_coloring::petgraph::graph::NodeIndex;
const COALESCING : bool = true; const COALESCING : bool = true;
pub struct GraphColoring<'a> { pub struct GraphColoring<'a> {
...@@ -21,30 +23,30 @@ pub struct GraphColoring<'a> { ...@@ -21,30 +23,30 @@ pub struct GraphColoring<'a> {
pub ig: InterferenceGraph, pub ig: InterferenceGraph,
precolored: LinkedHashSet<Node>, precolored: LinkedHashSet<NodeIndex>,
colors: HashMap<backend::RegGroup, LinkedHashSet<MuID>>, colors: HashMap<backend::RegGroup, LinkedHashSet<MuID>>,
pub colored_nodes: Vec<Node>, pub colored_nodes: Vec<NodeIndex>,
initial: Vec<Node>, initial: Vec<NodeIndex>,
degree: HashMap<Node, usize>, degree: HashMap<NodeIndex, usize>,
worklist_moves: Vec<Move>, worklist_moves: Vec<Move>,
movelist: HashMap<Node, RefCell<Vec<Move>>>, movelist: HashMap<NodeIndex, RefCell<Vec<Move>>>,
active_moves: LinkedHashSet<Move>, active_moves: LinkedHashSet<Move>,
coalesced_nodes: LinkedHashSet<Node>, coalesced_nodes: LinkedHashSet<NodeIndex>,
coalesced_moves: LinkedHashSet<Move>, coalesced_moves: LinkedHashSet<Move>,
constrained_moves: LinkedHashSet<Move>, constrained_moves: LinkedHashSet<Move>,
alias: HashMap<Node, Node>, alias: HashMap<NodeIndex, NodeIndex>,
worklist_spill: Vec<Node>, worklist_spill: Vec<NodeIndex>,
spillable: HashMap<MuID, bool>, spillable: HashMap<MuID, bool>,
spilled_nodes: Vec<Node>, spilled_nodes: Vec<NodeIndex>,
worklist_freeze: LinkedHashSet<Node>, worklist_freeze: LinkedHashSet<NodeIndex>,
frozen_moves: LinkedHashSet<Move>, frozen_moves: LinkedHashSet<Move>,
worklist_simplify: LinkedHashSet<Node>, worklist_simplify: LinkedHashSet<NodeIndex>,
select_stack: Vec<Node> select_stack: Vec<NodeIndex>
} }
impl <'a> GraphColoring<'a> { impl <'a> GraphColoring<'a> {
...@@ -95,7 +97,7 @@ impl <'a> GraphColoring<'a> { ...@@ -95,7 +97,7 @@ impl <'a> GraphColoring<'a> {
coloring.regalloc() coloring.regalloc()
} }
fn display_node(&self, node: Node) -> String { fn display_node(&self, node: NodeIndex) -> String {
let id = self.ig.get_temp_of(node); let id = self.ig.get_temp_of(node);
self.display_id(id) self.display_id(id)
} }
...@@ -215,15 +217,15 @@ impl <'a> GraphColoring<'a> { ...@@ -215,15 +217,15 @@ impl <'a> GraphColoring<'a> {
} }
} }
fn n_regs_for_node(&self, node: Node) -> usize { fn n_regs_for_node(&self, node: NodeIndex) -> usize {
backend::number_of_regs_in_group(self.ig.get_group_of(node)) backend::number_of_regs_in_group(self.ig.get_group_of(node))
} }
fn is_move_related(&mut self, node: Node) -> bool { fn is_move_related(&mut self, node: NodeIndex) -> bool {
!self.node_moves(node).is_empty() !self.node_moves(node).is_empty()
} }
fn node_moves(&mut self, node: Node) -> LinkedHashSet<Move> { fn node_moves(&mut self, node: NodeIndex) -> LinkedHashSet<Move> {
let mut moves = LinkedHashSet::new(); let mut moves = LinkedHashSet::new();
// addAll(active_moves) // addAll(active_moves)
...@@ -250,19 +252,19 @@ impl <'a> GraphColoring<'a> { ...@@ -250,19 +252,19 @@ impl <'a> GraphColoring<'a> {
// avoid using &mut self as argument // avoid using &mut self as argument
// in build(), we will need to mutate on self.movelist while // in build(), we will need to mutate on self.movelist while
// holding an immmutable reference of self(self.ig) // holding an immmutable reference of self(self.ig)
fn movelist_mut(list: &mut HashMap<Node, RefCell<Vec<Move>>>, node: Node) -> &RefCell<Vec<Move>> { fn movelist_mut(list: &mut HashMap<NodeIndex, RefCell<Vec<Move>>>, node: NodeIndex) -> &RefCell<Vec<Move>> {
GraphColoring::movelist_check(list, node); GraphColoring::movelist_check(list, node);
unsafe {GraphColoring::movelist_nocheck(list, node)} unsafe {GraphColoring::movelist_nocheck(list, node)}
} }
fn movelist_check(list: &mut HashMap<Node, RefCell<Vec<Move>>>, node: Node) { fn movelist_check(list: &mut HashMap<NodeIndex, RefCell<Vec<Move>>>, node: NodeIndex) {
if !list.contains_key(&node) { if !list.contains_key(&node) {
list.insert(node, RefCell::new(Vec::new())); list.insert(node, RefCell::new(Vec::new()));
} }
} }
// allows getting the Vec<Move> without a mutable reference of the hashmap // 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>> { unsafe fn movelist_nocheck(list: &HashMap<NodeIndex, RefCell<Vec<Move>>>, node: NodeIndex) -> &RefCell<Vec<Move>> {
list.get(&node).unwrap() list.get(&node).unwrap()
} }
...@@ -279,7 +281,7 @@ impl <'a> GraphColoring<'a> { ...@@ -279,7 +281,7 @@ impl <'a> GraphColoring<'a> {
} }
} }
fn adjacent(&self, n: Node) -> LinkedHashSet<Node> { fn adjacent(&self, n: NodeIndex) -> LinkedHashSet<NodeIndex> {
let mut adj = LinkedHashSet::new(); let mut adj = LinkedHashSet::new();
// add n's successors // add n's successors
...@@ -300,14 +302,14 @@ impl <'a> GraphColoring<'a> { ...@@ -300,14 +302,14 @@ impl <'a> GraphColoring<'a> {
adj adj
} }
fn degree(&self, n: Node) -> usize { fn degree(&self, n: NodeIndex) -> usize {
match self.degree.get(&n) { match self.degree.get(&n) {
Some(d) => *d, Some(d) => *d,
None => 0 None => 0
} }
} }
fn decrement_degree(&mut self, n: Node) { fn decrement_degree(&mut self, n: NodeIndex) {
if self.precolored.contains(&n) { if self.precolored.contains(&n) {
return; return;
} }
...@@ -337,7 +339,7 @@ impl <'a> GraphColoring<'a> { ...@@ -337,7 +339,7 @@ impl <'a> GraphColoring<'a> {
} }
} }
fn enable_moves(&mut self, nodes: LinkedHashSet<Node>) { fn enable_moves(&mut self, nodes: LinkedHashSet<NodeIndex>) {
for n in nodes.iter() { for n in nodes.iter() {
let n = *n; let n = *n;
for mov in self.node_moves(n).iter() { for mov in self.node_moves(n).iter() {
...@@ -410,7 +412,7 @@ impl <'a> GraphColoring<'a> { ...@@ -410,7 +412,7 @@ impl <'a> GraphColoring<'a> {
} }
} }
pub fn get_alias(&self, node: Node) -> Node { pub fn get_alias(&self, node: NodeIndex) -> NodeIndex {
if self.coalesced_nodes.contains(&node) { if self.coalesced_nodes.contains(&node) {
self.get_alias(*self.alias.get(&node).unwrap()) self.get_alias(*self.alias.get(&node).unwrap())
} else { } else {
...@@ -418,14 +420,14 @@ impl <'a> GraphColoring<'a> { ...@@ -418,14 +420,14 @@ impl <'a> GraphColoring<'a> {
} }
} }
fn add_worklist(&mut self, node: Node) { fn add_worklist(&mut self, node: NodeIndex) {
if !self.is_move_related(node) && self.degree(node) < self.n_regs_for_node(node) { if !self.is_move_related(node) && self.degree(node) < self.n_regs_for_node(node) {
self.worklist_freeze.remove(&node); self.worklist_freeze.remove(&node);
self.worklist_simplify.insert(node); self.worklist_simplify.insert(node);
} }
} }
fn ok(&self, u: Node, v: Node) -> bool { fn ok(&self, u: NodeIndex, v: NodeIndex) -> bool {
for t in self.adjacent(v).iter() { for t in self.adjacent(v).iter() {
let t = *t; let t = *t;
if !self.precolored.contains(&t) if !self.precolored.contains(&t)
...@@ -438,7 +440,7 @@ impl <'a> GraphColoring<'a> { ...@@ -438,7 +440,7 @@ impl <'a> GraphColoring<'a> {
true true
} }
fn conservative(&self, u: Node, v: Node) -> bool { fn conservative(&self, u: NodeIndex, v: NodeIndex) -> bool {
debug_assert!(self.ig.get_group_of(u) == self.ig.get_group_of(v)); debug_assert!(self.ig.get_group_of(u) == self.ig.get_group_of(v));
let adj_u = self.adjacent(u); let adj_u = self.adjacent(u);
...@@ -459,7 +461,7 @@ impl <'a> GraphColoring<'a> { ...@@ -459,7 +461,7 @@ impl <'a> GraphColoring<'a> {
k < self.n_regs_for_node(u) k < self.n_regs_for_node(u)
} }
fn combine(&mut self, u: Node, v: Node) { fn combine(&mut self, u: NodeIndex, v: NodeIndex) {
if self.worklist_freeze.contains(&v) { if self.worklist_freeze.contains(&v) {
self.worklist_freeze.remove(&v); self.worklist_freeze.remove(&v);
self.coalesced_nodes.insert(v); self.coalesced_nodes.insert(v);
...@@ -501,7 +503,7 @@ impl <'a> GraphColoring<'a> { ...@@ -501,7 +503,7 @@ impl <'a> GraphColoring<'a> {
} }
} }
fn add_edge(&mut self, u: Node, v: Node) { fn add_edge(&mut self, u: NodeIndex, v: NodeIndex) {
if u != v && !self.ig.is_adj(u, v) { if u != v && !self.ig.is_adj(u, v) {
if !self.precolored.contains(&u) { if !self.precolored.contains(&u) {
self.ig.add_interference_edge(u, v); self.ig.add_interference_edge(u, v);
...@@ -525,7 +527,7 @@ impl <'a> GraphColoring<'a> { ...@@ -525,7 +527,7 @@ impl <'a> GraphColoring<'a> {
self.freeze_moves(node); self.freeze_moves(node);
} }
fn freeze_moves(&mut self, u: Node) { fn freeze_moves(&mut self, u: NodeIndex) {
for m in self.node_moves(u).iter() { for m in self.node_moves(u).iter() {
let m = *m; let m = *m;
let mut v = self.get_alias(m.from); let mut v = self.get_alias(m.from);
...@@ -547,7 +549,7 @@ impl <'a> GraphColoring<'a> { ...@@ -547,7 +549,7 @@ impl <'a> GraphColoring<'a> {
fn select_spill(&mut self) { fn select_spill(&mut self) {
trace!("Selecting a node to spill..."); trace!("Selecting a node to spill...");
let mut m : Option<Node> = None; let mut m : Option<NodeIndex> = None;
for n in self.worklist_spill.iter() { for n in self.worklist_spill.iter() {
let n = *n; let n = *n;
......
extern crate nalgebra;
use compiler::machine_code::CompiledFunction; use compiler::machine_code::CompiledFunction;
use ast::ir::*; use ast::ir::*;
use compiler::backend; use compiler::backend;
...@@ -8,71 +6,62 @@ use utils::LinkedHashSet; ...@@ -8,71 +6,62 @@ use utils::LinkedHashSet;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use self::nalgebra::DMatrix; use compiler::backend::reg_alloc::graph_coloring::petgraph;
use compiler::backend::reg_alloc::graph_coloring::petgraph::Graph;
use compiler::backend::reg_alloc::graph_coloring::petgraph::graph::NodeIndex;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq)]
pub struct Node(usize); pub struct GraphNode {
#[derive(Clone, Debug, PartialEq)] temp: MuID,
pub struct NodeProperty {
color: Option<MuID>, color: Option<MuID>,
group: backend::RegGroup, group: backend::RegGroup,
temp: MuID,
spill_cost: f32 spill_cost: f32
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Move{pub from: Node, pub to: Node} pub struct Move{pub from: NodeIndex, pub to: NodeIndex}
pub struct InterferenceGraph { pub struct InterferenceGraph {
nodes: HashMap<MuID, Node>, graph: Graph<GraphNode, (), petgraph::Undirected>,
nodes_property: HashMap<Node, NodeProperty>, nodes: HashMap<MuID, NodeIndex>,
matrix: Option<DMatrix<bool>>,
moves: HashSet<Move>, moves: HashSet<Move>,
} }
impl InterferenceGraph { impl InterferenceGraph {
fn new() -> InterferenceGraph { fn new() -> InterferenceGraph {
InterferenceGraph { InterferenceGraph {
graph: Graph::new_undirected(),
nodes: HashMap::new(), nodes: HashMap::new(),
nodes_property: HashMap::new(),
matrix: None,
moves: HashSet::new() moves: HashSet::new()
} }
} }
fn new_node(&mut self, reg_id: MuID, context: &FunctionContext) -> Node { fn new_node(&mut self, reg_id: MuID, context: &FunctionContext) -> NodeIndex {
let entry = context.get_value(reg_id).unwrap(); let entry = context.get_value(reg_id).unwrap();
if !self.nodes.contains_key(&reg_id) { if !self.nodes.contains_key(&reg_id) {
let index = self.nodes.len(); let node = GraphNode {
let node = Node(index);
// add the node
self.nodes.insert(reg_id, node.clone());
// add node property
let group = backend::RegGroup::get(entry.ty());
let property = NodeProperty {
color: None,
group: group,
temp: reg_id, temp: reg_id,
color: None,
group: backend::RegGroup::get(entry.ty()),
spill_cost: 0.0f32 spill_cost: 0.0f32
}; };
self.nodes_property.insert(node, property);
} let index = self.graph.add_node(node);
self.nodes.insert(reg_id, index);
}
let node = * self.nodes.get(&reg_id).unwrap(); let node_index = *self.nodes.get(&reg_id).unwrap();
let node_mut = self.graph.node_weight_mut(node_index).unwrap();
// increase node spill cost // increase node spill cost
let property = self.nodes_property.get_mut(&node).unwrap(); node_mut.spill_cost += 1.0f32;
property.spill_cost += 1.0f32;
node node_index
} }
pub fn get_node(&self, reg: MuID) -> Node { pub fn get_node(&self, reg: MuID) -> NodeIndex {
match self.nodes.get(&reg) { match self.nodes.get(&reg) {
Some(index) => *index, Some(index) => *index,
None => panic!("do not have a node for {}", reg) None => panic!("do not have a node for {}", reg)
...@@ -87,10 +76,10 @@ impl InterferenceGraph { ...@@ -87,10 +76,10 @@ impl InterferenceGraph {
ret ret
} }
pub fn nodes(&self) -> Vec<Node> { pub fn nodes(&self) -> Vec<NodeIndex> {
let mut ret = vec![]; let mut ret = vec![];
for node in self.nodes.values() { for index in self.nodes.values() {
ret.push(node.clone()); ret.push(*index);
} }
ret ret
} }
...@@ -103,99 +92,70 @@ impl InterferenceGraph { ...@@ -103,99 +92,70 @@ impl InterferenceGraph {
self.nodes.len() self.nodes.len()
} }
fn init_graph(&mut self) { fn add_move(&mut self, src: NodeIndex, dst: NodeIndex) {
let len = self.nodes.len();
self.matrix = Some(DMatrix::from_element(len, len, false));
}
fn add_move(&mut self, src: Node, dst: Node) {
self.moves.insert(Move{from: src, to: dst}); self.moves.insert(Move{from: src, to: dst});
} }
pub fn is_same_group(&self, node1: Node, node2: Node) -> bool {
self.nodes_property.get(&node1).unwrap().group
== self.nodes_property.get(&node2).unwrap().group
}
pub fn add_interference_edge(&mut self, from: Node, to: Node) { pub fn add_interference_edge(&mut self, from: NodeIndex, to: NodeIndex) {
self.matrix.as_mut().unwrap()[(from.0, to.0)] = true; self.graph.update_edge(from, to, ());
} }
pub fn is_interferenced_with(&self, node1: Node, node2: Node) -> bool { pub fn is_interferenced_with(&self, node1: NodeIndex, node2: NodeIndex) -> bool {
self.matrix.as_ref().unwrap()[(node1.0, node2.0)] self.graph.find_edge(node1, node2).is_some()
|| self.matrix.as_ref().unwrap()[(node2.0, node1.0)]
} }
pub fn color_node(&mut self, node: Node, color: MuID) { pub fn color_node(&mut self, node: NodeIndex, color: MuID) {
self.nodes_property.get_mut(&node).unwrap().color = Some(color); self.graph.node_weight_mut(node).unwrap().color = Some(color);
} }
pub fn is_colored(&self, node: Node) -> bool { pub fn is_colored(&self, node: NodeIndex) -> bool {
self.nodes_property.get(&node).unwrap().color.is_some() self.graph.node_weight(node).unwrap().color.is_some()
} }
pub fn get_color_of(&self, node: Node) -> Option<MuID> { pub fn get_color_of(&self, node: NodeIndex) -> Option<MuID> {
self.nodes_property.get(&node).unwrap().color self.graph.node_weight(node).unwrap().color
} }
pub fn get_group_of(&self, node: Node) -> backend::RegGroup { pub fn get_group_of(&self, node: NodeIndex) -> backend::RegGroup {
self.nodes_property.get(&node).unwrap().group self.graph.node_weight(node).unwrap().group
} }
pub fn get_temp_of(&self, node: Node) -> MuID { pub fn get_temp_of(&self, node: NodeIndex) -> MuID {
self.nodes_property.get(&node).unwrap().temp self.graph.node_weight(node).unwrap().temp
} }
pub fn get_spill_cost(&self, node: Node) -> f32 { pub fn get_spill_cost(&self, node: NodeIndex) -> f32 {
self.nodes_property.get(&node).unwrap().spill_cost self.graph.node_weight(node).unwrap().spill_cost
} }
fn is_same_node(&self, node1: Node, node2: Node) -> bool { fn is_same_node(&self, node1: NodeIndex, node2: NodeIndex) -> bool {
node1 == node2 node1 == node2
} }
fn is_same_group(&self, node1: NodeIndex, node2: NodeIndex) -> bool {
let node1 = self.graph.node_weight(node1).unwrap();
let node2 = self.graph.node_weight(node2).unwrap();