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

Commit 970bbb22 authored by qinsoon's avatar qinsoon
Browse files

rewrite part of the register allocator

parent 332474a3
...@@ -20,13 +20,9 @@ use compiler::backend; ...@@ -20,13 +20,9 @@ use compiler::backend;
use utils::LinkedHashSet; use utils::LinkedHashSet;
use utils::LinkedHashMap; use utils::LinkedHashMap;
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;
/// GraphNode represents a node in the interference graph. /// GraphNode represents a node in the interference graph.
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub struct GraphNode { pub struct Node {
/// temp ID (could be register) /// temp ID (could be register)
temp: MuID, temp: MuID,
/// assigned color /// assigned color
...@@ -41,8 +37,17 @@ pub struct GraphNode { ...@@ -41,8 +37,17 @@ pub struct GraphNode {
/// We need to know the moves so that we can coalesce. /// We need to know the moves so that we can coalesce.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Move { pub struct Move {
pub from: NodeIndex, pub from: MuID,
pub to: NodeIndex pub to: MuID
}
#[inline(always)]
fn is_precolored(reg: MuID) -> bool {
if reg < MACHINE_ID_END {
true
} else {
false
}
} }
/// InterferenceGraph represents the interference graph, including /// InterferenceGraph represents the interference graph, including
...@@ -50,12 +55,11 @@ pub struct Move { ...@@ -50,12 +55,11 @@ pub struct Move {
/// * all the nodes and its NodeIndex (a node is referred to by NodeIndex) /// * all the nodes and its NodeIndex (a node is referred to by NodeIndex)
/// * all the moves /// * all the moves
pub struct InterferenceGraph { pub struct InterferenceGraph {
/// the internal graph nodes: LinkedHashMap<MuID, Node>,
graph: Graph<GraphNode, (), petgraph::Undirected>,
/// a map of all nodes (from temp ID to node index) adj_set: LinkedHashSet<(MuID, MuID)>,
/// node index is how nodes are referred to with pet_graph adj_list: LinkedHashMap<MuID, LinkedHashSet<MuID>>,
nodes: LinkedHashMap<MuID, NodeIndex>, degree: LinkedHashMap<MuID, usize>,
/// a set of all moves
moves: LinkedHashSet<Move> moves: LinkedHashSet<Move>
} }
...@@ -63,7 +67,9 @@ impl InterferenceGraph { ...@@ -63,7 +67,9 @@ impl InterferenceGraph {
/// creates a new graph /// creates a new graph
fn new() -> InterferenceGraph { fn new() -> InterferenceGraph {
InterferenceGraph { InterferenceGraph {
graph: Graph::new_undirected(), adj_set: LinkedHashSet::new(),
adj_list: LinkedHashMap::new(),
degree: LinkedHashMap::new(),
nodes: LinkedHashMap::new(), nodes: LinkedHashMap::new(),
moves: LinkedHashSet::new() moves: LinkedHashSet::new()
} }
...@@ -71,49 +77,34 @@ impl InterferenceGraph { ...@@ -71,49 +77,34 @@ impl InterferenceGraph {
/// creates a new node for a temp (if we already created a temp for the temp, returns the node) /// creates a new node for a temp (if we already created a temp for the temp, returns the node)
/// This function will increase spill cost for the node by 1 each tiem it is called for the temp /// This function will increase spill cost for the node by 1 each tiem it is called for the temp
fn new_node(&mut self, reg_id: MuID, context: &FunctionContext) -> NodeIndex { fn new_node(&mut self, reg_id: MuID, context: &FunctionContext) -> MuID {
let entry = context.get_value(reg_id).unwrap(); let entry = context.get_value(reg_id).unwrap();
// if it is the first time, create the node // if it is the first time, create the node
if !self.nodes.contains_key(&reg_id) { if !self.nodes.contains_key(&reg_id) {
let node = GraphNode { let node = Node {
temp: reg_id, temp: reg_id,
color: None, color: None,
group: backend::RegGroup::get_from_ty(entry.ty()), group: backend::RegGroup::get_from_ty(entry.ty()),
spill_cost: 0.0f32 spill_cost: 0.0f32
}; };
// add to the graph self.nodes.insert(reg_id, node);
let index = self.graph.add_node(node); self.adj_list.insert(reg_id, LinkedHashSet::new());
// save index self.degree.insert(reg_id, 0);
self.nodes.insert(reg_id, index);
} }
// get the node index
let node_index = *self.nodes.get(&reg_id).unwrap();
// get node // get node
let node_mut = self.graph.node_weight_mut(node_index).unwrap(); let node_mut = self.nodes.get_mut(&reg_id).unwrap();
// increase node spill cost // increase node spill cost
node_mut.spill_cost += 1.0f32; node_mut.spill_cost += 1.0f32;
node_index reg_id
}
/// returns the node index for a temp
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)
}
} }
/// returns all the nodes in the graph /// returns all the nodes in the graph
pub fn nodes(&self) -> Vec<NodeIndex> { pub fn nodes(&self) -> Vec<MuID> {
let mut ret = vec![]; self.nodes.keys().map(|x| *x).collect()
for index in self.nodes.values() {
ret.push(*index);
}
ret
} }
/// returns all the moves in the graph /// returns all the moves in the graph
...@@ -122,23 +113,19 @@ impl InterferenceGraph { ...@@ -122,23 +113,19 @@ impl InterferenceGraph {
} }
/// adds a move edge between two nodes /// adds a move edge between two nodes
fn add_move(&mut self, src: NodeIndex, dst: NodeIndex) { fn add_move(&mut self, src: MuID, dst: MuID) {
let src = { let src = {
let temp_src = self.get_temp_of(src); if is_precolored(src) {
if temp_src < MACHINE_ID_END {
// get the color for the machine register, e.g. rax for eax/ax/al/ah // get the color for the machine register, e.g. rax for eax/ax/al/ah
let alias = backend::get_color_for_precolored(temp_src); backend::get_color_for_precolored(src)
self.get_node(alias)
} else { } else {
src src
} }
}; };
let dst = { let dst = {
let temp_dst = self.get_temp_of(dst); if is_precolored(dst) {
if temp_dst < MACHINE_ID_END { backend::get_color_for_precolored(dst)
let alias = backend::get_color_for_precolored(temp_dst);
self.get_node(alias)
} else { } else {
dst dst
} }
...@@ -148,99 +135,88 @@ impl InterferenceGraph { ...@@ -148,99 +135,88 @@ impl InterferenceGraph {
} }
/// adds an interference edge between two nodes /// adds an interference edge between two nodes
pub fn add_interference_edge(&mut self, from: NodeIndex, to: NodeIndex) { pub fn add_edge(&mut self, u: MuID, v: MuID) {
// adds edge to the internal graph // // adds edge to the internal graph
self.graph.update_edge(from, to, ()); // self.graph.update_edge(from, to, ());
// if one of the node is machine register, we also add // if one of the node is machine register, we also add
// interference edge to its alias // interference edge to its alias
// e.g. if we have %a - %edi interfered, // e.g. if we have %a - %edi interfered,
// we also add %a - %rdi interference // we also add %a - %rdi interference
let from_tmp = self.graph.node_weight(from).unwrap().temp; if !self.adj_set.contains(&(u, v)) && u != v {
let to_tmp = self.graph.node_weight(to).unwrap().temp; self.adj_set.insert((u, v));
self.adj_set.insert((v, u));
if from_tmp < MACHINE_ID_END || to_tmp < MACHINE_ID_END {
let from_tmp = if from_tmp < MACHINE_ID_END {
backend::get_color_for_precolored(from_tmp)
} else {
from_tmp
};
let to_tmp = if to_tmp < MACHINE_ID_END {
backend::get_color_for_precolored(to_tmp)
} else {
to_tmp
};
let from_tmp_node = self.get_node(from_tmp); if !is_precolored(u) {
let to_tmp_node = self.get_node(to_tmp); self.adj_list.get_mut(&u).unwrap().insert(v);
self.graph.update_edge(from_tmp_node, to_tmp_node, ()); let degree = self.degree.get_mut(&u).unwrap();
*degree = *degree + 1;
}
if !is_precolored(v) {
self.adj_list.get_mut(&v).unwrap().insert(u);
let degree = self.degree.get_mut(&v).unwrap();
*degree = *degree + 1;
}
} }
} }
/// is two nodes interfered?
pub fn is_interfered_with(&self, node1: NodeIndex, node2: NodeIndex) -> bool {
let edge = self.graph.find_edge(node1, node2);
edge.is_some()
}
/// set color for a node /// set color for a node
pub fn color_node(&mut self, node: NodeIndex, color: MuID) { pub fn color_node(&mut self, reg: MuID, color: MuID) {
self.graph.node_weight_mut(node).unwrap().color = Some(color); self.nodes.get_mut(&reg).unwrap().color = Some(color);
} }
/// is a node colored yet? /// is a node colored yet?
pub fn is_colored(&self, node: NodeIndex) -> bool { pub fn is_colored(&self, reg: MuID) -> bool {
self.graph.node_weight(node).unwrap().color.is_some() self.nodes.get(&reg).unwrap().color.is_some()
} }
/// gets the color of a node /// gets the color of a node
pub fn get_color_of(&self, node: NodeIndex) -> Option<MuID> { pub fn get_color_of(&self, reg: MuID) -> Option<MuID> {
self.graph.node_weight(node).unwrap().color self.nodes.get(&reg).unwrap().color
} }
/// gets the reg group of a node /// gets the reg group of a node
pub fn get_group_of(&self, node: NodeIndex) -> backend::RegGroup { pub fn get_group_of(&self, reg: MuID) -> backend::RegGroup {
self.graph.node_weight(node).unwrap().group self.nodes.get(&reg).unwrap().group
} }
/// gets the temporary of a node /// gets the temporary of a node
pub fn get_temp_of(&self, node: NodeIndex) -> MuID { pub fn get_temp_of(&self, reg: MuID) -> MuID {
self.graph.node_weight(node).unwrap().temp self.nodes.get(&reg).unwrap().temp
} }
/// gets the spill cost of a node /// gets the spill cost of a node
pub fn get_spill_cost(&self, node: NodeIndex) -> f32 { pub fn get_spill_cost(&self, reg: MuID) -> f32 {
self.graph.node_weight(node).unwrap().spill_cost self.nodes.get(&reg).unwrap().spill_cost
} }
/// are two nodes the same node? /// are two nodes the same node?
fn is_same_node(&self, node1: NodeIndex, node2: NodeIndex) -> bool { fn is_same_node(&self, reg1: MuID, reg2: MuID) -> bool {
node1 == node2 reg1 == reg2
} }
/// are two nodes from the same reg group? /// are two nodes from the same reg group?
fn is_same_group(&self, node1: NodeIndex, node2: NodeIndex) -> bool { fn is_same_group(&self, reg1: MuID, reg2: MuID) -> bool {
let node1 = self.graph.node_weight(node1).unwrap(); self.get_group_of(reg1) == self.get_group_of(reg2)
let node2 = self.graph.node_weight(node2).unwrap();
node1.group == node2.group
} }
/// are two nodes adjacent? /// gets edges from a node
pub fn is_adj(&self, from: NodeIndex, to: NodeIndex) -> bool { pub fn get_adj_list(&self, reg: MuID) -> &LinkedHashSet<MuID> {
self.is_interfered_with(from, to) self.adj_list.get(&reg).unwrap()
} }
/// gets edges from a node pub fn is_in_adj_set(&self, u: MuID, v: MuID) -> bool {
pub fn get_edges_of(&self, node: NodeIndex) -> Vec<NodeIndex> { self.adj_set.contains(&(u, v))
self.graph.neighbors(node).collect()
} }
/// gets degree of a node (number of edges from the node) /// gets degree of a node (number of edges from the node)
pub fn get_degree_of(&self, node: NodeIndex) -> usize { pub fn get_degree_of(&self, reg: MuID) -> usize {
self.get_edges_of(node).len() *self.degree.get(&reg).unwrap()
}
pub fn set_degree_of(&mut self, reg: MuID, degree: usize) {
*self.degree.get_mut(&reg).unwrap() = degree;
} }
/// prints current graph for debugging (via trace log) /// prints current graph for debugging (via trace log)
...@@ -251,23 +227,7 @@ impl InterferenceGraph { ...@@ -251,23 +227,7 @@ impl InterferenceGraph {
trace!(""); trace!("");
trace!("Interference Graph"); trace!("Interference Graph");
trace!("nodes:"); trace!("not available");
for id in self.nodes.keys() {
let val = context.get_value(*id).unwrap().value();
trace!("Reg {} -> {:?}", val, self.nodes.get(&id).unwrap());
}
trace!("moves:");
for mov in self.moves.iter() {
trace!("Move {:?} -> {:?}", mov.from, mov.to);
}
trace!("graph:");
trace!(
"\n\n{:?}\n",
Dot::with_config(&self.graph, &[Config::EdgeNoLabel])
);
trace!("");
} }
} }
...@@ -360,17 +320,17 @@ pub fn build_interference_graph_chaitin_briggs( ...@@ -360,17 +320,17 @@ pub fn build_interference_graph_chaitin_briggs(
None None
} else { } else {
if src.len() == 1 { if src.len() == 1 {
let node1 = ig.get_node(src[0]); let src = src[0];
let node2 = ig.get_node(dst[0]); let dst = dst[0];
trace_if!( trace_if!(
TRACE_LIVENESS, TRACE_LIVENESS,
"add move between {} and {}", "add move between {} and {}",
func.context.get_temp_display(src[0]), func.context.get_temp_display(src),
func.context.get_temp_display(dst[0]) func.context.get_temp_display(dst)
); );
ig.add_move(node1, node2); ig.add_move(src, dst);
Some(src[0]) Some(src)
} else { } else {
None None
} }
...@@ -406,12 +366,10 @@ pub fn build_interference_graph_chaitin_briggs( ...@@ -406,12 +366,10 @@ pub fn build_interference_graph_chaitin_briggs(
func.context.get_temp_display(*e) func.context.get_temp_display(*e)
); );
if src.is_none() || (src.is_some() && *e != src.unwrap()) { if src.is_none() || (src.is_some() && *e != src.unwrap()) {
let from = ig.get_node(d); let from = d;
let to = ig.get_node(*e); let to = *e;
if !ig.is_same_node(from, to) && ig.is_same_group(from, to) && if !ig.is_same_node(from, to) && ig.is_same_group(from, to) {
!ig.is_adj(from, to)
{
if !ig.is_colored(from) { if !ig.is_colored(from) {
trace_if!( trace_if!(
TRACE_LIVENESS, TRACE_LIVENESS,
...@@ -421,7 +379,7 @@ pub fn build_interference_graph_chaitin_briggs( ...@@ -421,7 +379,7 @@ pub fn build_interference_graph_chaitin_briggs(
func.context.get_temp_display(d), func.context.get_temp_display(d),
func.context.get_temp_display(*e) func.context.get_temp_display(*e)
); );
ig.add_interference_edge(from, to); ig.add_edge(from, to);
} }
if !ig.is_colored(to) { if !ig.is_colored(to) {
trace_if!( trace_if!(
...@@ -432,7 +390,7 @@ pub fn build_interference_graph_chaitin_briggs( ...@@ -432,7 +390,7 @@ pub fn build_interference_graph_chaitin_briggs(
func.context.get_temp_display(*e), func.context.get_temp_display(*e),
func.context.get_temp_display(d) func.context.get_temp_display(d)
); );
ig.add_interference_edge(to, from); ig.add_edge(to, from);
} }
} }
} }
......
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