Commit 4b4b7298 authored by qinsoon's avatar qinsoon

[wip] remove jump-to-jump in peephole opt for x86_64

parent 924e2b3e
Pipeline #742 canceled with stages
in 78 minutes and 13 seconds
......@@ -759,6 +759,13 @@ 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];
asm.code = format!("jmp {}", symbol(mangle_name(String::from(new_dest))));
}
/// set an instruction as nop
fn set_inst_nop(&mut self, index: usize) {
self.code[index].code.clear();
......
......@@ -40,6 +40,20 @@ impl CompilerPass for PeepholeOptimization {
for i in 0..cf.mc().number_of_insts() {
// if two sides of a move instruction are the same, it is redundant, and can be eliminated
self.remove_redundant_move(i, &mut cf);
// if a branch jumps a label that contains another jump, such as
// ..
// jmp L1
// ..
// L1:
// jmp L2
// ..
// 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
self.remove_jump_to_jump(i, &mut cf);
// if a branch targets a block that immediately follow it, it can be eliminated
self.remove_unnecessary_jump(i, &mut cf);
}
......@@ -127,4 +141,32 @@ 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);
}
None => return
}
}
None => return
}
}
}
......@@ -208,6 +208,8 @@ pub trait MachineCode {
fn replace_define_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
/// 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);
/// 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