GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit 19c5b2c0 authored by qinsoon's avatar qinsoon

[wip] backbone of graph coloring

parent d570c55c
......@@ -12,6 +12,7 @@ pub use compiler::backend::x86_64::asm_backend::ASMCodeGen;
use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
use compiler::backend::RegGroup;
macro_rules! GPR {
($name: expr, $id: expr) => {
......@@ -79,6 +80,25 @@ lazy_static! {
R14.clone(),
R15.clone()
];
pub static ref ALL_GPRs : [P<Value>; 16] = [
RAX.clone(),
RCX.clone(),
RDX.clone(),
RBX.clone(),
RSP.clone(),
RBP.clone(),
RSI.clone(),
RDI.clone(),
R8.clone(),
R9.clone(),
R10.clone(),
R11.clone(),
R12.clone(),
R13.clone(),
R14.clone(),
R15.clone()
];
}
lazy_static!{
......@@ -114,6 +134,25 @@ lazy_static!{
];
pub static ref CALLEE_SAVED_FPRs : [P<Value>; 0] = [];
pub static ref ALL_FPRs : [P<Value>; 16] = [
XMM0.clone(),
XMM1.clone(),
XMM2.clone(),
XMM3.clone(),
XMM4.clone(),
XMM5.clone(),
XMM6.clone(),
XMM7.clone(),
XMM8.clone(),
XMM9.clone(),
XMM10.clone(),
XMM11.clone(),
XMM12.clone(),
XMM13.clone(),
XMM14.clone(),
XMM15.clone(),
];
}
pub const GPR_COUNT : usize = 16;
......@@ -156,17 +195,39 @@ lazy_static! {
];
}
pub fn get_name_for_value(id: MuID, func_context: &FunctionContext) -> &'static str {
if id < RESERVED_NODE_IDS_FOR_MACHINE {
ALL_MACHINE_REGs[id].tag
} else {
match func_context.get_value(id) {
Some(ref v) => v.tag,
None => panic!("cannot find tag for node id={}", id)
}
pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
use std::cell::Cell;
for reg in ALL_MACHINE_REGs.iter() {
let reg_id = reg.extract_ssa_id().unwrap();
let entry = SSAVarEntry {
id: reg_id,
tag: reg.tag,
ty: reg.ty.clone(),
use_count: Cell::new(0),
expr: None
};
func_context.value_tags.insert(reg.tag, reg_id);
func_context.values.insert(reg_id, entry);
}
}
pub fn number_of_regs_in_group(group: RegGroup) -> usize {
match group {
RegGroup::GPR => ALL_GPRs.len(),
RegGroup::FPR => ALL_FPRs.len()
}
}
pub fn number_of_all_regs() -> usize {
ALL_MACHINE_REGs.len()
}
pub fn all_regs() -> &'static Vec<P<Value>> {
&ALL_MACHINE_REGs
}
pub fn is_valid_x86_imm(op: &P<Value>) -> bool {
use std::u32;
match op.v {
......
pub mod inst_sel;
pub mod reg_alloc;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RegGroup {GPR, FPR}
#[cfg(target_arch = "x86_64")]
#[path = "arch/x86_64/mod.rs"]
mod x86_64;
#[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"]
mod arm;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::get_name_for_value;
pub use compiler::backend::x86_64::init_machine_regs_for_func;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::GPR_COUNT;
pub use compiler::backend::x86_64::number_of_regs_in_group;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::FPR_COUNT;
pub use compiler::backend::x86_64::number_of_all_regs;
#[cfg(target_arch = "x86_64")]
pub use compiler::backend::x86_64::all_regs;
#[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"]
mod arm;
#[cfg(target_arch = "arm")]
pub use compiler::backend::arm::GPR_COUNT;
......
use compiler::backend::reg_alloc::liveness::InterferenceGraph;
use ast::ir::MuID;
use compiler::backend::reg_alloc::liveness::InterferenceGraph;
use compiler::backend::reg_alloc::liveness::{Node, Move};
use vm::machine_code::CompiledFunction;
use compiler::backend::GPR_COUNT;
use compiler::backend;
use compiler::backend::reg_alloc::liveness::find_value;
use std::collections::LinkedList;
use std::collections::HashSet;
use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
const COALESCING : AtomicBool = ATOMIC_BOOL_INIT;
pub struct GraphColoring <'a> {
ig: InterferenceGraph,
cur_cf: &'a CompiledFunction,
K: usize
precolored: HashSet<Node>,
colors: HashSet<MuID>,
initial: LinkedList<Node>,
degree: HashMap<Node, usize>,
worklist_moves: LinkedList<Move>,
movelist: HashMap<Node, Vec<Move>>,
active_moves: HashSet<Move>,
worklist_spill: LinkedList<Node>,
worklist_freeze: HashSet<Node>,
worklist_simplify: HashSet<Node>
}
impl <'a> GraphColoring <'a> {
......@@ -14,13 +37,151 @@ impl <'a> GraphColoring <'a> {
let mut coloring = GraphColoring {
ig: ig,
cur_cf: cf,
K: 0
precolored: HashSet::new(),
colors: HashSet::new(),
initial: LinkedList::new(),
degree: HashMap::new(),
worklist_moves: LinkedList::new(),
movelist: HashMap::new(),
active_moves: HashSet::new(),
worklist_spill: LinkedList::new(),
worklist_freeze: HashSet::new(),
worklist_simplify: HashSet::new()
};
coloring.init();
}
fn init (&mut self) {
self.K = GPR_COUNT;
COALESCING.store(true, Ordering::Relaxed);
for reg in backend::all_regs().iter() {
let reg_id = reg.extract_ssa_id().unwrap();
let node = self.ig.get_node(reg_id);
self.precolored.insert(node);
self.colors.insert(reg_id);
}
for node in self.ig.nodes() {
if !self.ig.is_colored(node) {
self.initial.push_back(node);
self.degree.insert(node, self.ig.outdegree_of(node));
}
}
self.build();
self.make_work_list();
while {
if !self.worklist_simplify.is_empty() {
self.simplify();
} else if !self.worklist_moves.is_empty() {
self.coalesce();
} else if !self.worklist_freeze.is_empty() {
self.freeze();
} else if !self.worklist_spill.is_empty() {
self.select_spill();
}
! (self.worklist_simplify.is_empty()
&& self.worklist_moves.is_empty()
&& self.worklist_freeze.is_empty()
&& self.worklist_spill.is_empty())
} {}
self.assign_colors();
}
fn simplify(&mut self) {
unimplemented!()
}
fn coalesce(&mut self) {
unimplemented!()
}
fn freeze(&mut self) {
unimplemented!()
}
fn select_spill(&mut self) {
unimplemented!()
}
fn assign_colors(&mut self) {
unimplemented!()
}
fn build(&mut self) {
if COALESCING.load(Ordering::Relaxed) {
let ref ig = self.ig;
let ref mut movelist = self.movelist;
for m in ig.moves() {
self.worklist_moves.push_back(m.clone());
GraphColoring::movelist_mut(movelist, m.from).push(m.clone());
GraphColoring::movelist_mut(movelist, m.to).push(m.clone());
}
}
}
fn make_work_list(&mut self) {
while !self.initial.is_empty() {
let node = self.initial.pop_front().unwrap();
if {
// condition: degree >= K
let degree = self.ig.degree_of(node);
let n_regs = backend::number_of_regs_in_group(self.ig.get_group_of(node));
degree >= n_regs
} {
self.worklist_spill.push_back(node);
} else if self.is_move_related(node) {
self.worklist_freeze.insert(node);
} else {
self.worklist_simplify.insert(node);
}
}
}
fn is_move_related(&mut self, node: Node) -> bool {
!self.node_moves(node).is_empty()
}
fn node_moves(&mut self, node: Node) -> HashSet<Move> {
let mut moves = HashSet::new();
// addAll(active_moves)
for m in self.active_moves.iter() {
moves.insert(m.clone());
}
// addAll(worklist_moves)
for m in self.worklist_moves.iter() {
moves.insert(m.clone());
}
let mut retained = HashSet::new();
let movelist = GraphColoring::movelist_mut(&mut self.movelist, node);
for m in moves.iter() {
if find_value(movelist, *m).is_some() {
retained.insert(*m);
}
}
retained
}
fn movelist_mut(list: &mut HashMap<Node, Vec<Move>>, node: Node) -> &mut Vec<Move> {
if !list.contains_key(&node) {
list.insert(node, Vec::new());
}
list.get_mut(&node).unwrap()
}
}
\ No newline at end of file
This diff is collapsed.
#![allow(dead_code)]
use compiler::CompilerPass;
use ast::ir::*;
use vm::context::VMContext;
use compiler::backend::init_machine_regs_for_func;
mod liveness;
mod coloring;
......@@ -29,7 +33,10 @@ impl CompilerPass for RegisterAllocation {
cf.mc.print();
let liveness = liveness::build(&mut cf);
// initialize machine registers for the function context
init_machine_regs_for_func(&mut func.context);
let liveness = liveness::build(&mut cf, func);
liveness.print();
coloring::GraphColoring::start(&mut cf, liveness);
......
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