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,7 +25,6 @@ libloading = "0.3"
lazy_static = "0.1.15"
log = "0.3.5"
simple_logger = "0.4.0"
nalgebra = "0.8.2"
hprof = "0.1.3"
memmap = "0.4.0"
memsec = "0.1.9"
......@@ -33,3 +32,4 @@ rustc-serialize = "*"
time = "0.1.34"
maplit = "0.1.4"
docopt = "0.6"
petgraph = "0.4.1"
\ No newline at end of file
......@@ -2,7 +2,6 @@ use ast::ir::*;
use compiler::backend;
use compiler::backend::reg_alloc::graph_coloring;
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 vm::VM;
......@@ -12,6 +11,9 @@ use utils::LinkedHashSet;
use std::cell::RefCell;
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;
pub struct GraphColoring<'a> {
......@@ -21,30 +23,30 @@ pub struct GraphColoring<'a> {
pub ig: InterferenceGraph,
precolored: LinkedHashSet<Node>,
precolored: LinkedHashSet<NodeIndex>,
colors: HashMap<backend::RegGroup, LinkedHashSet<MuID>>,
pub colored_nodes: Vec<Node>,
pub colored_nodes: Vec<NodeIndex>,
initial: Vec<Node>,
degree: HashMap<Node, usize>,
initial: Vec<NodeIndex>,
degree: HashMap<NodeIndex, usize>,
worklist_moves: Vec<Move>,
movelist: HashMap<Node, RefCell<Vec<Move>>>,
movelist: HashMap<NodeIndex, RefCell<Vec<Move>>>,
active_moves: LinkedHashSet<Move>,
coalesced_nodes: LinkedHashSet<Node>,
coalesced_nodes: LinkedHashSet<NodeIndex>,
coalesced_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>,
spilled_nodes: Vec<Node>,
spilled_nodes: Vec<NodeIndex>,
worklist_freeze: LinkedHashSet<Node>,
worklist_freeze: LinkedHashSet<NodeIndex>,
frozen_moves: LinkedHashSet<Move>,
worklist_simplify: LinkedHashSet<Node>,
select_stack: Vec<Node>
worklist_simplify: LinkedHashSet<NodeIndex>,
select_stack: Vec<NodeIndex>
}
impl <'a> GraphColoring<'a> {
......@@ -95,7 +97,7 @@ impl <'a> GraphColoring<'a> {
coloring.regalloc()
}
fn display_node(&self, node: Node) -> String {
fn display_node(&self, node: NodeIndex) -> String {
let id = self.ig.get_temp_of(node);
self.display_id(id)
}
......@@ -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))
}
fn is_move_related(&mut self, node: Node) -> bool {
fn is_move_related(&mut self, node: NodeIndex) -> bool {
!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();
// addAll(active_moves)
......@@ -250,19 +252,19 @@ impl <'a> GraphColoring<'a> {
// 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>> {
fn movelist_mut(list: &mut HashMap<NodeIndex, RefCell<Vec<Move>>>, node: NodeIndex) -> &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) {
fn movelist_check(list: &mut HashMap<NodeIndex, RefCell<Vec<Move>>>, node: NodeIndex) {
if !list.contains_key(&node) {
list.insert(node, RefCell::new(Vec::new()));
}
}
// 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()
}
......@@ -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();
// add n's successors
......@@ -300,14 +302,14 @@ impl <'a> GraphColoring<'a> {
adj
}
fn degree(&self, n: Node) -> usize {
fn degree(&self, n: NodeIndex) -> usize {
match self.degree.get(&n) {
Some(d) => *d,
None => 0
}
}
fn decrement_degree(&mut self, n: Node) {
fn decrement_degree(&mut self, n: NodeIndex) {
if self.precolored.contains(&n) {
return;
}
......@@ -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() {
let n = *n;
for mov in self.node_moves(n).iter() {
......@@ -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) {
self.get_alias(*self.alias.get(&node).unwrap())
} else {
......@@ -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) {
self.worklist_freeze.remove(&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() {
let t = *t;
if !self.precolored.contains(&t)
......@@ -438,7 +440,7 @@ impl <'a> GraphColoring<'a> {
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));
let adj_u = self.adjacent(u);
......@@ -459,7 +461,7 @@ impl <'a> GraphColoring<'a> {
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) {
self.worklist_freeze.remove(&v);
self.coalesced_nodes.insert(v);
......@@ -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 !self.precolored.contains(&u) {
self.ig.add_interference_edge(u, v);
......@@ -525,7 +527,7 @@ impl <'a> GraphColoring<'a> {
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() {
let m = *m;
let mut v = self.get_alias(m.from);
......@@ -547,7 +549,7 @@ impl <'a> GraphColoring<'a> {
fn select_spill(&mut self) {
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() {
let n = *n;
......
extern crate nalgebra;
use compiler::machine_code::CompiledFunction;
use ast::ir::*;
use compiler::backend;
......@@ -8,71 +6,62 @@ use utils::LinkedHashSet;
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)]
pub struct Node(usize);
#[derive(Clone, Debug, PartialEq)]
pub struct NodeProperty {
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct GraphNode {
temp: MuID,
color: Option<MuID>,
group: backend::RegGroup,
temp: MuID,
spill_cost: f32
}
#[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 {
nodes: HashMap<MuID, Node>,
nodes_property: HashMap<Node, NodeProperty>,
matrix: Option<DMatrix<bool>>,
graph: Graph<GraphNode, (), petgraph::Undirected>,
nodes: HashMap<MuID, NodeIndex>,
moves: HashSet<Move>,
}
impl InterferenceGraph {
fn new() -> InterferenceGraph {
InterferenceGraph {
graph: Graph::new_undirected(),
nodes: HashMap::new(),
nodes_property: HashMap::new(),
matrix: None,
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();
if !self.nodes.contains_key(&reg_id) {
let index = self.nodes.len();
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,
let node = GraphNode {
temp: reg_id,
color: None,
group: backend::RegGroup::get(entry.ty()),
spill_cost: 0.0f32
};
self.nodes_property.insert(node, property);
}
let index = self.graph.add_node(node);
let node = * self.nodes.get(&reg_id).unwrap();
self.nodes.insert(reg_id, index);
}
let node_index = *self.nodes.get(&reg_id).unwrap();
let node_mut = self.graph.node_weight_mut(node_index).unwrap();
// increase node spill cost
let property = self.nodes_property.get_mut(&node).unwrap();
property.spill_cost += 1.0f32;
node_mut.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) {
Some(index) => *index,
None => panic!("do not have a node for {}", reg)
......@@ -87,10 +76,10 @@ impl InterferenceGraph {
ret
}
pub fn nodes(&self) -> Vec<Node> {
pub fn nodes(&self) -> Vec<NodeIndex> {
let mut ret = vec![];
for node in self.nodes.values() {
ret.push(node.clone());
for index in self.nodes.values() {
ret.push(*index);
}
ret
}
......@@ -103,99 +92,70 @@ impl InterferenceGraph {
self.nodes.len()
}
fn init_graph(&mut self) {
let len = self.nodes.len();
self.matrix = Some(DMatrix::from_element(len, len, false));
}
fn add_move(&mut self, src: Node, dst: Node) {
fn add_move(&mut self, src: NodeIndex, dst: NodeIndex) {
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) {
self.matrix.as_mut().unwrap()[(from.0, to.0)] = true;
pub fn add_interference_edge(&mut self, from: NodeIndex, to: NodeIndex) {
self.graph.update_edge(from, to, ());
}
pub fn is_interferenced_with(&self, node1: Node, node2: Node) -> bool {
self.matrix.as_ref().unwrap()[(node1.0, node2.0)]
|| self.matrix.as_ref().unwrap()[(node2.0, node1.0)]
pub fn is_interferenced_with(&self, node1: NodeIndex, node2: NodeIndex) -> bool {
self.graph.find_edge(node1, node2).is_some()
}
pub fn color_node(&mut self, node: Node, color: MuID) {
self.nodes_property.get_mut(&node).unwrap().color = Some(color);
pub fn color_node(&mut self, node: NodeIndex, color: MuID) {
self.graph.node_weight_mut(node).unwrap().color = Some(color);
}
pub fn is_colored(&self, node: Node) -> bool {
self.nodes_property.get(&node).unwrap().color.is_some()
pub fn is_colored(&self, node: NodeIndex) -> bool {
self.graph.node_weight(node).unwrap().color.is_some()
}
pub fn get_color_of(&self, node: Node) -> Option<MuID> {
self.nodes_property.get(&node).unwrap().color
pub fn get_color_of(&self, node: NodeIndex) -> Option<MuID> {
self.graph.node_weight(node).unwrap().color
}
pub fn get_group_of(&self, node: Node) -> backend::RegGroup {
self.nodes_property.get(&node).unwrap().group
pub fn get_group_of(&self, node: NodeIndex) -> backend::RegGroup {
self.graph.node_weight(node).unwrap().group
}
pub fn get_temp_of(&self, node: Node) -> MuID {
self.nodes_property.get(&node).unwrap().temp
pub fn get_temp_of(&self, node: NodeIndex) -> MuID {
self.graph.node_weight(node).unwrap().temp
}
pub fn get_spill_cost(&self, node: Node) -> f32 {
self.nodes_property.get(&node).unwrap().spill_cost
pub fn get_spill_cost(&self, node: NodeIndex) -> f32 {
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
}
pub fn is_adj(&self, from: Node, to: Node) -> bool {
let ref matrix = self.matrix.as_ref().unwrap();
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();
matrix[(from.0, to.0)] || matrix[(to.0, from.0)]
node1.group == node2.group
}
pub fn outedges_of(&self, node: Node) -> Vec<Node> {
let mut ret = vec![];
let matrix = self.matrix.as_ref().unwrap();
for i in 0..self.nodes.len() {
if matrix[(node.0, i)] {
ret.push(Node(i));
}
pub fn is_adj(&self, from: NodeIndex, to: NodeIndex) -> bool {
self.is_interferenced_with(from, to)
}
ret
pub fn outedges_of(&self, node: NodeIndex) -> Vec<NodeIndex> {
self.graph.neighbors(node).collect()
}
pub fn outdegree_of(&self, node: Node) -> usize {
let mut count = 0;
for i in 0..self.nodes.len() {
if self.matrix.as_ref().unwrap()[(node.0, i)] {
count += 1;
}
pub fn outdegree_of(&self, node: NodeIndex) -> usize {
self.outedges_of(node).len()
}
count
}
pub fn indegree_of(&self, node: Node) -> usize {
let mut count = 0;
for i in 0..self.nodes.len() {
if self.matrix.as_ref().unwrap()[(i, node.0)] {
count += 1;
}
}
count
pub fn indegree_of(&self, node: NodeIndex) -> usize {
self.outdegree_of(node)
}
pub fn degree_of(&self, node: Node) -> usize {
pub fn degree_of(&self, node: NodeIndex) -> usize {
self.outdegree_of(node)
}
......@@ -209,43 +169,13 @@ impl InterferenceGraph {
debug!("Reg {} -> {:?}", val, self.nodes.get(&id).unwrap());
}
debug!("color:");
for (node, color) in self.nodes_property.iter() {
let node_val = context.get_value(self.get_temp_of(*node)).unwrap().value();
let color_val = context.get_value(color.temp).unwrap().value();
debug!("Reg {} of {:?} -> Color/Reg {}", node_val, node, color_val);
}
debug!("moves:");
for mov in self.moves.iter() {
debug!("Move {:?} -> {:?}", mov.from, mov.to);
}
debug!("graph:");
{
let node_to_reg_id = {
let mut ret : HashMap<Node, MuID> = HashMap::new();
for reg in self.nodes.keys() {
ret.insert(*self.nodes.get(reg).unwrap(), *reg);
}
ret
};
let matrix = self.matrix.as_ref().unwrap();
for i in 0..matrix.ncols() {
for j in 0..matrix.nrows() {
if matrix[(i, j)] {
let from_node = node_to_reg_id.get(&Node(i)).unwrap();
let to_node = node_to_reg_id.get(&Node(j)).unwrap();
let from_val = context.get_value(*from_node).unwrap().value();
let to_val = context.get_value(*to_node).unwrap().value();
debug!("Reg {} -> Reg {}", from_val, to_val);
}
}
}
}
debug!("graph:");
debug!("{:?}", self.graph);
debug!("");
}
}
......@@ -335,9 +265,6 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
}
}
// all nodes has been added, we init graph (create adjacency matrix)
ig.init_graph();
for block in cf.mc().get_all_blocks() {
// Current_Live(B) = LiveOut(B)
let mut current_live = LinkedHashSet::from_vec(match cf.mc().get_ir_block_liveout(&block) {
......
extern crate petgraph;
mod liveness;
mod coloring;
......
extern crate mu;
use common::*;
use test_ir::test_ir::factorial;
use test_ir::test_ir::sum;
use self::mu::ast::ir::*;
......
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