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 { ...@@ -51,6 +51,33 @@ impl CopyPropagation {
} }
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) { fn move_lattice(&mut self, dst: MuID, src: MuID) {
trace!("Move lattice for Move {} -> {}", src, dst); trace!("Move lattice for Move {} -> {}", src, dst);
...@@ -81,6 +108,8 @@ impl CopyPropagation { ...@@ -81,6 +108,8 @@ impl CopyPropagation {
self.lattices.insert(dst, new_lattice); 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) { fn resolve_lattice(&mut self) {
self.trace_print_lattices("Lattice built from the code"); self.trace_print_lattices("Lattice built from the code");
// resolve a->b->c as a->c // resolve a->b->c as a->c
...@@ -158,6 +187,7 @@ impl CopyPropagation { ...@@ -158,6 +187,7 @@ impl CopyPropagation {
self.trace_print_lattices("Final Lattices"); self.trace_print_lattices("Final Lattices");
} }
/// re-adds all the MaybeMerge into current work queue
fn update_work_queue(&self, queue: &mut Vec<MuID>) { fn update_work_queue(&self, queue: &mut Vec<MuID>) {
for (id, lattice) in self.lattices.iter() { for (id, lattice) in self.lattices.iter() {
match lattice { match lattice {
...@@ -167,6 +197,7 @@ impl CopyPropagation { ...@@ -167,6 +197,7 @@ impl CopyPropagation {
} }
} }
/// debug prints
fn trace_print_lattices(&self, msg: &'static str) { fn trace_print_lattices(&self, msg: &'static str) {
trace!("---{}---", msg); trace!("---{}---", msg);
for (id, lattice) in self.lattices.iter() { for (id, lattice) in self.lattices.iter() {
...@@ -174,6 +205,7 @@ impl CopyPropagation { ...@@ -174,6 +205,7 @@ impl CopyPropagation {
} }
} }
/// updates current lattices - resolve chain copies, and replace everything with their copy
fn update_lattices(&mut self) { 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 // 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> = { let copies: HashMap<MuID, MuID> = {
...@@ -223,31 +255,106 @@ impl CopyPropagation { ...@@ -223,31 +255,106 @@ impl CopyPropagation {
} }
} }
fn process_dest( /// rewrites the function with given copy propagation results
&mut self, fn rewrite(&self, func: &mut MuFunctionVersion) {
inst: &Instruction, let rewrite_table: HashMap<MuID, P<Value>> = {
dest: &Destination, let mut ret = HashMap::new();
f_content: &FunctionContent for (id, lattice) in self.lattices.iter() {
) { match lattice {
for i in 0..dest.args.len() { &CopyLattice::Copy(src) => {
let ref arg = dest.args[i]; ret.insert(*id, func.context.get_value(src).unwrap().value().clone());
match arg { }
&DestArg::Normal(index) => { _ => {}
let src = inst.ops[index].as_value(); }
}
ret
};
if src.is_reg() { for (id, block) in func.content.as_mut().unwrap().blocks.iter_mut() {
let dst = { let block_content = block.content.as_ref().unwrap().clone();
let target_block = f_content.get_block(dest.target.id());
let args = &target_block.content.as_ref().unwrap().args; // rewrite body
&args[i] 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
}; };
self.move_lattice(dst.id(), src.id()); 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
});
} }
} }
_ => unimplemented!()
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);
}
}
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()
}
}
} }
impl CompilerPass for CopyPropagation { impl CompilerPass for CopyPropagation {
...@@ -323,6 +430,16 @@ impl CompilerPass for CopyPropagation { ...@@ -323,6 +430,16 @@ impl CompilerPass for CopyPropagation {
} }
fn finish_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) { fn finish_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
// resolve MaybeMerge
self.resolve_lattice(); 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