Commit 24fe689e authored by qinsoon's avatar qinsoon

peephole optimization for removing jump-to-jump should work for x86_64

parent 4b4b7298
Pipeline #745 passed with stages
in 29 minutes and 35 seconds
......@@ -629,6 +629,10 @@ impl MachineCode for ASMCode {
}
}
fn replace_branch_dest(&mut self, inst: usize, new_dest: &str, succ: usize) {
unimplemented!()
}
fn set_inst_nop(&mut self, index: usize) {
self.code[index].code.clear();
// self.code.remove(index);
......
......@@ -760,10 +760,21 @@ impl MachineCode for ASMCode {
}
/// replace destination for a jump instruction
fn replace_branch_dest(&mut self, inst: usize, new_dest: &str) {
let asm = &mut self.code[inst];
fn replace_branch_dest(&mut self, inst: usize, new_dest: &str, succ: MuID) {
{
let asm = &mut self.code[inst];
asm.code = format!("jmp {}", symbol(mangle_name(String::from(new_dest))));
asm.code = format!("jmp {}", symbol(mangle_name(String::from(new_dest))));
asm.succs.clear();
asm.succs.push(succ);
}
{
let asm = &mut self.code[succ];
if !asm.preds.contains(&inst) {
asm.preds.push(inst);
}
}
}
/// set an instruction as nop
......
......@@ -51,7 +51,7 @@ impl CompilerPass for PeepholeOptimization {
// we can rewrite first branch to jump to L2 directly
// the order matters: we need to run this first, then remove_unnecessary_jump()
// as this opt will give us more chances to remove unnecessary jumps
// as this will give us more chances to remove unnecessary jumps
self.remove_jump_to_jump(i, &mut cf);
// if a branch targets a block that immediately follow it, it can be eliminated
......@@ -104,7 +104,7 @@ impl PeepholeOptimization {
// check if two registers are aliased
if backend::is_aliased(src_machine_reg, dst_machine_reg) {
trace!("move between {} and {} is redundant! removed", src_machine_reg, dst_machine_reg);
info!("move between {} and {} is redundant! removed", src_machine_reg, dst_machine_reg);
// redundant, remove this move
cf.mc_mut().set_inst_nop(inst);
} else {
......@@ -129,7 +129,8 @@ impl PeepholeOptimization {
let opt_label = mc.is_label(inst + 1);
match opt_label {
Some(ref label) if dest == label => {
mc.set_inst_nop(inst);
info!("inst {}'s jmp to {} is unnecessary! removed", inst, label);
mc.set_inst_nop(inst);
}
_ => {
// do nothing
......@@ -145,28 +146,52 @@ impl PeepholeOptimization {
fn remove_jump_to_jump(&mut self, inst: usize, cf: &mut CompiledFunction) {
let mut mc = cf.mc_mut();
let opt_dest = mc.is_jmp(inst);
match opt_dest {
Some(ref dest) => {
// get the block for destination
let start = mc.get_block_range(dest).unwrap().start;
// get the first instruction
let first_inst = match mc.get_next_inst(start) {
Some(i) => i,
None => return
};
match mc.is_jmp(first_inst) {
Some(ref dest2) => {
// its a jump-to-jump case
// change destination of 1st jump to the 2nd destination
mc.replace_branch_dest(inst, dest2);
// the instruction that we may rewrite
let orig_inst = inst;
// the destination we will rewrite the instruction to branch to
let final_dest : Option<MuName> = {
let mut cur_inst = inst;
let mut last_dest = None;
loop {
let opt_dest = mc.is_jmp(cur_inst);
match opt_dest {
Some(ref dest) => {
// get the block for destination
let first_inst = mc.get_block_range(dest).unwrap().start;
debug_assert!(mc.is_label(first_inst).is_none(), "expect start inst {} of \
block {} is a inst instead of label", first_inst, dest);
trace!("examining first inst {} of block {}", first_inst, dest);
// if first instruction is jump
match mc.is_jmp(first_inst) {
Some(ref dest2) => {
// its a jump-to-jump case
cur_inst = first_inst;
last_dest = Some(dest2.clone());
}
None => break
}
}
None => return
None => break
}
}
None => return
last_dest
};
if let Some(dest) = final_dest {
let first_inst = {
let start = mc.get_block_range(&dest).unwrap().start;
match mc.get_next_inst(start) {
Some(i) => i,
None => panic!("we are jumping to a block {}\
that does not have instructions?", dest)
}
};
info!("inst {} chain jumps to {}, rewrite as branching to {} (successor: {})",
orig_inst, dest, dest, first_inst);
mc.replace_branch_dest(inst, &dest, first_inst);
}
}
}
......@@ -209,7 +209,7 @@ pub trait MachineCode {
/// replace a temp that is used in the inst with another temp
fn replace_use_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
/// replace destination for an unconditional branch instruction
fn replace_branch_dest(&mut self, inst: usize, new_dest: &str);
fn replace_branch_dest(&mut self, inst: usize, new_dest: &str, succ: usize);
/// set an instruction as nop
fn set_inst_nop(&mut self, index: usize);
/// remove unnecessary push/pop if the callee saved register is not used
......
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