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.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.6% of users enabled 2FA.

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