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.7% of users enabled 2FA.

Commit c22425e4 authored by qinsoon's avatar qinsoon
Browse files

[wip] consider coalescing during validating

parent 7f5165b0
......@@ -720,4 +720,18 @@ impl <'a> GraphColoring<'a> {
pub fn get_spill_history(&self) -> LinkedHashMap<MuID, P<Value>> {
self.spill_history.clone()
}
pub fn get_coalesced(&self) -> LinkedHashMap<MuID, MuID> {
let mut ret = LinkedHashMap::new();
for mov in self.coalesced_moves.iter() {
let from = self.ig.get_temp_of(mov.from);
let to = self.ig.get_temp_of(mov.to);
ret.insert(from, to);
ret.insert(to , from);
}
ret
}
}
......@@ -41,8 +41,9 @@ impl RegisterAllocation {
if !vm.vm_options.flag_disable_regalloc_validate {
let reg_assignment = coloring.get_assignments();
let reg_spilled = coloring.get_spill_history();
let reg_coalesced = coloring.get_coalesced();
validate::validate_regalloc(&coloring.cf, &coloring.func, reg_assignment, reg_spilled)
validate::validate_regalloc(&coloring.cf, &coloring.func, reg_assignment, reg_coalesced, reg_spilled)
}
// replace regs
......
......@@ -168,6 +168,23 @@ pub struct RegisterEntry {
}
impl RegisterEntry {
pub fn has_temp(&self) -> bool {
self.temp.is_some()
}
pub fn has_real(&self) -> bool {
!self.real.is_empty()
}
pub fn has_stack_slots(&self) -> bool {
!self.stack.is_empty()
}
pub fn set_temp(&mut self, temp: MuID) {
self.temp = Some(temp);
}
pub fn get_temp(&self) -> Option<MuID> {
self.temp.clone()
}
pub fn match_temp(&self, temp: MuID) -> bool {
if self.temp.is_some() && self.temp.unwrap() == temp {
true
......
......@@ -65,6 +65,13 @@ impl ExactLiveness {
self.kill.insert(*i, kill);
}
}
pub fn get_liveout(&self, index: usize) -> Option<LinkedHashSet<MuID>> {
match self.liveout.get(&index) {
Some(s) => Some(s.clone()),
None => None
}
}
pub fn get_kills(&self, index: usize) -> Option<LinkedHashSet<MuID>> {
match self.kill.get(&index) {
......
......@@ -13,10 +13,16 @@ use compiler::backend::reg_alloc::validate::exact_liveness::*;
pub fn validate_regalloc(cf: &CompiledFunction,
func: &MuFunctionVersion,
reg_assigned: LinkedHashMap<MuID, MuID>,
reg_coalesced:LinkedHashMap<MuID, MuID>,
reg_spilled: LinkedHashMap<MuID, P<Value>>)
{
debug!("---Validating register allocation results---");
debug!("coalesced registers: ");
for (a, b) in reg_coalesced.iter() {
debug!("{} -> {}", a, b);
}
debug!("liveness analysis...");
let liveness = ExactLiveness::new(cf);
for i in 0..cf.mc().number_of_insts() {
......@@ -51,7 +57,7 @@ pub fn validate_regalloc(cf: &CompiledFunction,
for i in 0..mc.number_of_insts() {
mc.trace_inst(i);
if mc.is_jump(i) {
if mc.is_jmp(i).is_some() {
// we need to flow-sensitive analysis
unimplemented!();
}
......@@ -63,13 +69,20 @@ pub fn validate_regalloc(cf: &CompiledFunction,
// remove kills in the inst from alive entries
if let Some(kills) = liveness.get_kills(i) {
for reg in kills.iter() {
remove_kill(*reg, &reg_assigned, &mut alive);
kill_reg(*reg, &reg_assigned, &mut alive);
}
}
// add defines to alive entries
for reg_def in mc.get_inst_reg_defines(i) {
add_def(reg_def, &reg_assigned, &mut alive);
let liveout = liveness.get_liveout(i).unwrap();
// if reg is in the liveout set, we add a define to it
if liveout.contains(&reg_def) {
add_def(reg_def, &reg_assigned, &reg_coalesced, &mut alive);
} else {
kill_reg(reg_def, &reg_assigned, &mut alive);
}
}
debug!("{}", alive);
......@@ -115,7 +128,7 @@ fn validate_use(reg: MuID, reg_assigned: &LinkedHashMap<MuID, MuID>, alive: &Ali
}
}
fn remove_kill(reg: MuID, reg_assigned: &LinkedHashMap<MuID, MuID>, alive: &mut AliveEntries) {
fn kill_reg(reg: MuID, reg_assigned: &LinkedHashMap<MuID, MuID>, alive: &mut AliveEntries) {
if reg < MACHINE_ID_END {
if alive.find_entry_for_reg(reg).is_some() {
alive.remove_reg(reg);
......@@ -127,17 +140,59 @@ fn remove_kill(reg: MuID, reg_assigned: &LinkedHashMap<MuID, MuID>, alive: &mut
}
}
fn add_def(reg: MuID, reg_assigned: &LinkedHashMap<MuID, MuID>, alive: &mut AliveEntries) {
fn add_def(reg: MuID, reg_assigned: &LinkedHashMap<MuID, MuID>, reg_coalesced: &LinkedHashMap<MuID, MuID>, alive: &mut AliveEntries) {
if reg < MACHINE_ID_END {
// if it is a machine register
// we require either it doesn't have an entry,
// or its entry doesnt have a temp, so that we can safely overwrite it
if alive.find_entry_for_reg(reg).is_none() {
// add new machine register
alive.new_alive_reg(reg);
} else if !alive.find_entry_for_reg(reg).unwrap().has_temp() {
// overwrite it
} else {
let old_temp = alive.find_entry_for_reg(reg).unwrap().get_temp().unwrap();
error!("Register{}/Temp{} is alive at this point, defining a new value to Register{} is incorrect", reg, old_temp, reg);
panic!("validation failed: define a register that is already alive (value overwritten)");
}
} else {
let machine_reg = get_machine_reg(reg, reg_assigned);
let temp = reg;
alive.add_temp_in_reg(temp, machine_reg);
if alive.find_entry_for_reg(machine_reg).is_none() {
// if this register is not alive, we add an entry for it
alive.add_temp_in_reg(temp, machine_reg);
} else {
// otherwise, this register contains some value
{
let entry = alive.find_entry_for_reg_mut(machine_reg).unwrap();
if !entry.has_temp() {
debug!("adding temp {} to reg {}", temp, machine_reg);
entry.set_temp(temp);
} else {
// if the register is holding a temporary, it needs to be coalesced with new temp
let old_temp: MuID = entry.get_temp().unwrap();
if (reg_coalesced.contains_key(&old_temp) && *reg_coalesced.get(&old_temp).unwrap() == temp)
|| (reg_coalesced.contains_key(&temp) && *reg_coalesced.get(&temp).unwrap() == old_temp)
{
// coalesced, safe
} else {
// not coalesced, error
error!("Temp{} and Temp{} are not coalesced, but they use the same Register{}", temp, old_temp, machine_reg);
panic!("validation failed: define a register that is already alive, and their temps are not coalesced");
}
}
}
// they are coalesced, it is valid
alive.add_temp_in_reg(temp, machine_reg);
}
}
}
......
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