To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

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"
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"
rustc-serialize = "*"
time = "0.1.34"
maplit = "0.1.4"
docopt = "0.6"
\ No newline at end of file
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);
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
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
}
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();
node1.group == node2.group
}
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)]
pub fn is_adj(&self, from: NodeIndex, to: NodeIndex) -> bool {
self.is_interferenced_with(from, to)
}
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));
}
}
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;
}
}
count
pub fn outdegree_of(&self, node: NodeIndex) -> usize {
self.outedges_of(node).len()
}
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