WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit 4b4b7298 authored by qinsoon's avatar qinsoon
Browse files

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

parent 924e2b3e
......@@ -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) {
......@@ -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