GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

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; ...@@ -12,6 +12,7 @@ pub use compiler::backend::x86_64::asm_backend::ASMCodeGen;
use ast::ptr::P; use ast::ptr::P;
use ast::ir::*; use ast::ir::*;
use ast::types::*; use ast::types::*;
use compiler::backend::RegGroup;
macro_rules! GPR { macro_rules! GPR {
($name: expr, $id: expr) => { ($name: expr, $id: expr) => {
...@@ -79,6 +80,25 @@ lazy_static! { ...@@ -79,6 +80,25 @@ lazy_static! {
R14.clone(), R14.clone(),
R15.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!{ lazy_static!{
...@@ -114,6 +134,25 @@ lazy_static!{ ...@@ -114,6 +134,25 @@ lazy_static!{
]; ];
pub static ref CALLEE_SAVED_FPRs : [P<Value>; 0] = []; 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; pub const GPR_COUNT : usize = 16;
...@@ -156,17 +195,39 @@ lazy_static! { ...@@ -156,17 +195,39 @@ lazy_static! {
]; ];
} }
pub fn get_name_for_value(id: MuID, func_context: &FunctionContext) -> &'static str { pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
if id < RESERVED_NODE_IDS_FOR_MACHINE { use std::cell::Cell;
ALL_MACHINE_REGs[id].tag
} else { for reg in ALL_MACHINE_REGs.iter() {
match func_context.get_value(id) { let reg_id = reg.extract_ssa_id().unwrap();
Some(ref v) => v.tag, let entry = SSAVarEntry {
None => panic!("cannot find tag for node id={}", id) 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 { pub fn is_valid_x86_imm(op: &P<Value>) -> bool {
use std::u32; use std::u32;
match op.v { match op.v {
......
pub mod inst_sel; pub mod inst_sel;
pub mod reg_alloc; pub mod reg_alloc;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RegGroup {GPR, FPR}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[path = "arch/x86_64/mod.rs"] #[path = "arch/x86_64/mod.rs"]
mod x86_64; mod x86_64;
#[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"]
mod arm;
#[cfg(target_arch = "x86_64")] #[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")] #[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")] #[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")] #[cfg(target_arch = "arm")]
pub use compiler::backend::arm::GPR_COUNT; 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 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> { pub struct GraphColoring <'a> {
ig: InterferenceGraph, ig: InterferenceGraph,
cur_cf: &'a CompiledFunction, 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> { impl <'a> GraphColoring <'a> {
...@@ -14,13 +37,151 @@ impl <'a> GraphColoring <'a> { ...@@ -14,13 +37,151 @@ impl <'a> GraphColoring <'a> {
let mut coloring = GraphColoring { let mut coloring = GraphColoring {
ig: ig, ig: ig,
cur_cf: cf, 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(); coloring.init();
} }
fn init (&mut self) { 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 compiler::CompilerPass;
use ast::ir::*; use ast::ir::*;
use vm::context::VMContext; use vm::context::VMContext;
use compiler::backend::init_machine_regs_for_func;
mod liveness; mod liveness;
mod coloring; mod coloring;
...@@ -29,7 +33,10 @@ impl CompilerPass for RegisterAllocation { ...@@ -29,7 +33,10 @@ impl CompilerPass for RegisterAllocation {
cf.mc.print(); 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(); liveness.print();
coloring::GraphColoring::start(&mut cf, liveness); 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