GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Commit 24fe689e authored by qinsoon's avatar qinsoon

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

parent 4b4b7298
......@@ -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