mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
YJIT: eliminate redundant mov in csel/cmov on x86 (#6348)
* Eliminate redundant mov in csel/cmov. Translate mov reg,0 into xor * Fix x86 asm test * Remove dbg!() * xor optimization unsound because it resets flags
This commit is contained in:
parent
2a08a39d7d
commit
5b5c627d37
Notes:
git
2022-09-10 07:41:48 +09:00
Merged-By: maximecb <maximecb@ruby-lang.org>
1 changed files with 31 additions and 24 deletions
|
@ -145,7 +145,7 @@ impl Assembler
|
||||||
if !value.special_const_p() || imm_num_bits(value.as_i64()) > 32 {
|
if !value.special_const_p() || imm_num_bits(value.as_i64()) > 32 {
|
||||||
asm.load(iterator.map_opnd(*opnd))
|
asm.load(iterator.map_opnd(*opnd))
|
||||||
} else {
|
} else {
|
||||||
iterator.map_opnd(*opnd)
|
Opnd::UImm(value.as_u64())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iterator.map_opnd(*opnd)
|
iterator.map_opnd(*opnd)
|
||||||
|
@ -221,18 +221,25 @@ impl Assembler
|
||||||
Insn::CSelLE { truthy, falsy, out } |
|
Insn::CSelLE { truthy, falsy, out } |
|
||||||
Insn::CSelG { truthy, falsy, out } |
|
Insn::CSelG { truthy, falsy, out } |
|
||||||
Insn::CSelGE { truthy, falsy, out } => {
|
Insn::CSelGE { truthy, falsy, out } => {
|
||||||
match truthy {
|
match unmapped_opnds[0] {
|
||||||
Opnd::Reg(_) | Opnd::InsnOut { .. } => {},
|
// If we have an instruction output whose live range
|
||||||
_ => {
|
// spans beyond this instruction, we have to load it.
|
||||||
|
Opnd::InsnOut { idx, .. } => {
|
||||||
|
if live_ranges[idx] > index {
|
||||||
|
*truthy = asm.load(*truthy);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Opnd::UImm(_) | Opnd::Imm(_) | Opnd::Value(_) => {
|
||||||
*truthy = asm.load(*truthy);
|
*truthy = asm.load(*truthy);
|
||||||
}
|
},
|
||||||
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
match falsy {
|
match falsy {
|
||||||
Opnd::Reg(_) | Opnd::InsnOut { .. } => {},
|
Opnd::UImm(_) | Opnd::Imm(_) => {
|
||||||
_ => {
|
|
||||||
*falsy = asm.load(*falsy);
|
*falsy = asm.load(*falsy);
|
||||||
}
|
},
|
||||||
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
*out = asm.next_opnd_out(Opnd::match_num_bits(&[*truthy, *falsy]));
|
*out = asm.next_opnd_out(Opnd::match_num_bits(&[*truthy, *falsy]));
|
||||||
|
@ -350,6 +357,14 @@ impl Assembler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn emit_csel(cb: &mut CodeBlock, truthy: Opnd, falsy: Opnd, out: Opnd, cmov_fn: fn(&mut CodeBlock, X86Opnd, X86Opnd)) {
|
||||||
|
if out != truthy {
|
||||||
|
mov(cb, out.into(), truthy.into());
|
||||||
|
}
|
||||||
|
cmov_fn(cb, out.into(), falsy.into());
|
||||||
|
}
|
||||||
|
|
||||||
//dbg!(&self.insns);
|
//dbg!(&self.insns);
|
||||||
|
|
||||||
// List of GC offsets
|
// List of GC offsets
|
||||||
|
@ -609,36 +624,28 @@ impl Assembler
|
||||||
Insn::Breakpoint => int3(cb),
|
Insn::Breakpoint => int3(cb),
|
||||||
|
|
||||||
Insn::CSelZ { truthy, falsy, out } => {
|
Insn::CSelZ { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmovnz);
|
||||||
cmovnz(cb, out.into(), falsy.into());
|
|
||||||
},
|
},
|
||||||
Insn::CSelNZ { truthy, falsy, out } => {
|
Insn::CSelNZ { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmovz);
|
||||||
cmovz(cb, out.into(), falsy.into());
|
|
||||||
},
|
},
|
||||||
Insn::CSelE { truthy, falsy, out } => {
|
Insn::CSelE { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmovne);
|
||||||
cmovne(cb, out.into(), falsy.into());
|
|
||||||
},
|
},
|
||||||
Insn::CSelNE { truthy, falsy, out } => {
|
Insn::CSelNE { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmove);
|
||||||
cmove(cb, out.into(), falsy.into());
|
|
||||||
},
|
},
|
||||||
Insn::CSelL { truthy, falsy, out } => {
|
Insn::CSelL { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmovge);
|
||||||
cmovge(cb, out.into(), falsy.into());
|
|
||||||
},
|
},
|
||||||
Insn::CSelLE { truthy, falsy, out } => {
|
Insn::CSelLE { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmovg);
|
||||||
cmovg(cb, out.into(), falsy.into());
|
|
||||||
},
|
},
|
||||||
Insn::CSelG { truthy, falsy, out } => {
|
Insn::CSelG { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmovle);
|
||||||
cmovle(cb, out.into(), falsy.into());
|
|
||||||
},
|
},
|
||||||
Insn::CSelGE { truthy, falsy, out } => {
|
Insn::CSelGE { truthy, falsy, out } => {
|
||||||
mov(cb, out.into(), truthy.into());
|
emit_csel(cb, *truthy, *falsy, *out, cmovl);
|
||||||
cmovl(cb, out.into(), falsy.into());
|
|
||||||
}
|
}
|
||||||
Insn::LiveReg { .. } => (), // just a reg alloc signal, no code
|
Insn::LiveReg { .. } => (), // just a reg alloc signal, no code
|
||||||
Insn::PadEntryExit => {
|
Insn::PadEntryExit => {
|
||||||
|
|
Loading…
Reference in a new issue