Commit 68e6ddd6 authored by qinsoon's avatar qinsoon

rewrite SSA variables based on copy propagation results

parent 21552828
Pipeline #1403 failed with stages
in 21 minutes and 40 seconds
......@@ -51,6 +51,33 @@ impl CopyPropagation {
}
impl CopyPropagation {
fn process_dest(
&mut self,
inst: &Instruction,
dest: &Destination,
f_content: &FunctionContent
) {
for i in 0..dest.args.len() {
let ref arg = dest.args[i];
match arg {
&DestArg::Normal(index) => {
let src = inst.ops[index].as_value();
if src.is_reg() {
let dst = {
let target_block = f_content.get_block(dest.target.id());
let args = &target_block.content.as_ref().unwrap().args;
&args[i]
};
self.move_lattice(dst.id(), src.id());
}
}
_ => unimplemented!()
}
}
}
/// adds a new move from src to dst, and change lattice corespondingly
fn move_lattice(&mut self, dst: MuID, src: MuID) {
trace!("Move lattice for Move {} -> {}", src, dst);
......@@ -81,6 +108,8 @@ impl CopyPropagation {
self.lattices.insert(dst, new_lattice);
}
/// resolves lattice after iterating through the instructions
/// Mainly resolve MaybeMerge into either a Copy or a Merge
fn resolve_lattice(&mut self) {
self.trace_print_lattices("Lattice built from the code");
// resolve a->b->c as a->c
......@@ -158,6 +187,7 @@ impl CopyPropagation {
self.trace_print_lattices("Final Lattices");
}
/// re-adds all the MaybeMerge into current work queue
fn update_work_queue(&self, queue: &mut Vec<MuID>) {
for (id, lattice) in self.lattices.iter() {
match lattice {
......@@ -167,6 +197,7 @@ impl CopyPropagation {
}
}
/// debug prints
fn trace_print_lattices(&self, msg: &'static str) {
trace!("---{}---", msg);
for (id, lattice) in self.lattices.iter() {
......@@ -174,6 +205,7 @@ impl CopyPropagation {
}
}
/// updates current lattices - resolve chain copies, and replace everything with their copy
fn update_lattices(&mut self) {
// resolve copy - if a is a copy of b, b is a copy of c, then a is a copy of c
let copies: HashMap<MuID, MuID> = {
......@@ -223,29 +255,104 @@ impl CopyPropagation {
}
}
fn process_dest(
&mut self,
inst: &Instruction,
dest: &Destination,
f_content: &FunctionContent
) {
for i in 0..dest.args.len() {
let ref arg = dest.args[i];
match arg {
&DestArg::Normal(index) => {
let src = inst.ops[index].as_value();
/// rewrites the function with given copy propagation results
fn rewrite(&self, func: &mut MuFunctionVersion) {
let rewrite_table: HashMap<MuID, P<Value>> = {
let mut ret = HashMap::new();
for (id, lattice) in self.lattices.iter() {
match lattice {
&CopyLattice::Copy(src) => {
ret.insert(*id, func.context.get_value(src).unwrap().value().clone());
}
_ => {}
}
}
ret
};
if src.is_reg() {
let dst = {
let target_block = f_content.get_block(dest.target.id());
let args = &target_block.content.as_ref().unwrap().args;
&args[i]
};
self.move_lattice(dst.id(), src.id());
for (id, block) in func.content.as_mut().unwrap().blocks.iter_mut() {
let block_content = block.content.as_ref().unwrap().clone();
// rewrite body
let mut new_body = vec![];
for node in block_content.body.iter() {
new_body.push(self.rewrite_node(node, &rewrite_table));
}
// rewrite args/exn-arg/keepalives
let new_args: Vec<P<Value>> = block_content
.args
.iter()
.map(|x| self.rewrite_value(x, &rewrite_table))
.collect();
let new_exn_arg = if block_content.exn_arg.is_some() {
Some(self.rewrite_value(
block_content.exn_arg.as_ref().unwrap(),
&rewrite_table
))
} else {
None
};
let new_keepalives: Option<Vec<P<Value>>> = if block_content.keepalives.is_some() {
Some(
block_content
.keepalives
.as_ref()
.unwrap()
.iter()
.map(|x| self.rewrite_value(x, &rewrite_table))
.collect()
)
} else {
None
};
block.content = Some(BlockContent {
args: new_args,
exn_arg: new_exn_arg,
body: new_body,
keepalives: new_keepalives
});
}
}
fn rewrite_node(&self, node: &P<TreeNode>, table: &HashMap<MuID, P<Value>>) -> P<TreeNode> {
match node.v {
TreeNode_::Value(ref pv) => TreeNode::new_value(self.rewrite_value(pv, table)),
TreeNode_::Instruction(ref inst) => {
let mut new_inst: Instruction = inst.clone();
// make changes to new_inst, and release all the borrows
{
// if we replace value
if new_inst.value.is_some() {
let values = new_inst.value.as_mut().unwrap();
for i in 0..values.len() {
values[i] = self.rewrite_value(&values[i], table);
}
}
// if we replace operands
let ops = &mut new_inst.ops;
for i in 0..ops.len() {
ops[i] = self.rewrite_node(&ops[i], table);
}
}
_ => unimplemented!()
TreeNode::new_inst(new_inst)
}
}
}
fn rewrite_value(&self, val: &P<Value>, table: &HashMap<MuID, P<Value>>) -> P<Value> {
if val.is_reg() {
let ssa_id = val.extract_ssa_id().unwrap();
if table.contains_key(&ssa_id) {
table.get(&ssa_id).unwrap().clone()
} else {
val.clone()
}
} else {
val.clone()
}
}
}
......@@ -323,6 +430,16 @@ impl CompilerPass for CopyPropagation {
}
fn finish_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
// resolve MaybeMerge
self.resolve_lattice();
trace!("---before rewriting---");
trace!("{:?}", func);
// rewrite nodes by replacing values to its actual source
self.rewrite(func);
trace!("---after rewriting---");
trace!("{:?}", func);
}
}
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