Commit d152c68c authored by qinsoon's avatar qinsoon

validating register allocation

when proceeding to a new block, prune alive entries based on liveout and
liveins
parent 1461b6f1
......@@ -2870,7 +2870,12 @@ impl <'a> InstructionSelection {
unimplemented!()
},
&Constant::NullRef => {
self.backend.emit_xor_r_r(&tmp, &tmp);
// xor a, a -> a will mess up register allocation validation
// since it uses a regsiter with arbitrary value
// self.backend.emit_xor_r_r(&tmp, &tmp);
// for now, use mov -> a
self.backend.emit_mov_r_imm(&tmp, 0);
},
_ => panic!("expected ireg")
}
......
......@@ -251,7 +251,6 @@ impl AliveEntries {
}
} else {
// find entry without a temp in the other set and do intersect
for another_entry in another.inner.values() {
if !another_entry.has_temp() {
if entry.intersect(another_entry) {
......@@ -264,6 +263,40 @@ impl AliveEntries {
changed
}
pub fn preserve_list(&mut self, list: &Vec<MuID>) {
let mut indices_to_delete : Vec<EntryID> = vec![];
for (index, entry) in self.inner.iter() {
if !entry.has_temp() {
if list.iter().any(|x| entry.match_reg(*x)) {
} else {
indices_to_delete.push(*index);
}
} else {
let temp = entry.get_temp().unwrap();
if !vec_utils::find_value(list, temp).is_some() {
indices_to_delete.push(*index);
}
}
}
// always preserve entries with spill location
let mut indices_to_really_delete : Vec<EntryID> = vec![];
for index in indices_to_delete {
let entry = self.inner.get(&index).unwrap();
if !entry.has_stack_slots() {
indices_to_really_delete.push(index);
}
}
// delete
for index in indices_to_really_delete {
self.inner.remove(&index);
}
}
}
#[derive(Clone)]
......
......@@ -133,6 +133,16 @@ pub fn validate_regalloc(cf: &CompiledFunction,
trace!("---");
}
// find liveout of the block, and only preserve what is in the liveout
let liveout = match mc.get_ir_block_liveout(&block) {
Some(liveout) => liveout,
None => panic!("cannot find liveout for block {}", block)
};
alive.preserve_list(liveout);
debug!("liveout is {:?}", liveout);
debug!("preserve only entries in liveout, we get:");
debug!("{}", alive);
// find succeeding blocks
let succeeding_blocks : Vec<MuName> = mc.get_succs(last_inst).iter()
.map(|x| match mc.is_label(*x - 1) {
......@@ -168,13 +178,37 @@ pub fn validate_regalloc(cf: &CompiledFunction,
debug!("push block {} to work list", succeeding_blocks[0]);
} else if succeeding_blocks.len() == 2 {
// conditional branch
// FIXME: need to prune alive entries based on live in
// it is possible that a variable is alive at the end of a BB, and used
// only in one of its successors
work_queue.insert(succeeding_blocks[0].clone(), alive.clone());
work_queue.insert(succeeding_blocks[1].clone(), alive.clone());
debug!("push block {} to work list", succeeding_blocks[0]);
debug!("push block {} to work list", succeeding_blocks[1]);
// 1st branch
{
let block1 = succeeding_blocks[0].clone();
let block1_livein = match mc.get_ir_block_livein(&block1) {
Some(livein) => livein,
None => panic!("cannot find livein for block {}", block1)
};
let mut block1_alive = alive.clone();
block1_alive.preserve_list(block1_livein);
work_queue.insert(block1, block1_alive);
debug!("push block {} to work list", succeeding_blocks[0]);
}
// 2nd branch
{
let block2 = succeeding_blocks[1].clone();
let block2_livein = match mc.get_ir_block_livein(&block2) {
Some(livein) => livein,
None => panic!("cannot find livein for block {}", block2)
};
let mut block2_alive = alive.clone();
block2_alive.preserve_list(block2_livein);
work_queue.insert(block2, block2_alive);
debug!("push block {} to work list", succeeding_blocks[1]);
}
}
}
......
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