YJIT: Merge add/sub/and/or/xor and mov on x86_64 (#7492)

This commit is contained in:
Takashi Kokubun 2023-03-13 13:32:45 -07:00 committed by GitHub
parent 309ff928f5
commit c7822b8dbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
Notes: git 2023-03-13 20:33:06 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>

View File

@ -166,6 +166,16 @@ impl Assembler
Insn::And { left, right, out } |
Insn::Or { left, right, out } |
Insn::Xor { left, right, out } => {
match (&left, &right, iterator.peek()) {
// Merge this insn, e.g. `add REG, right -> out`, and `mov REG, out` if possible
(Opnd::Reg(_), Opnd::UImm(value), Some(Insn::Mov { dest, src }))
if out == src && left == dest && live_ranges[index] == index + 1 && uimm_num_bits(*value) <= 32 => {
*out = *dest;
asm.push_insn(insn);
iterator.map_insn_index(&mut asm);
iterator.next_unmapped(); // Pop merged Insn::Mov
}
_ => {
match (unmapped_opnds[0], unmapped_opnds[1]) {
(Opnd::Mem(_), Opnd::Mem(_)) => {
*left = asm.load(*left);
@ -189,6 +199,8 @@ impl Assembler
*out = asm.next_opnd_out(Opnd::match_num_bits(&[*left, *right]));
asm.push_insn(insn);
}
}
},
Insn::Cmp { left, right } => {
// Replace `cmp REG, 0` (4 bytes) with `test REG, REG` (3 bytes)
@ -953,4 +965,59 @@ mod tests {
assert_eq!(format!("{:x}", cb), "488b43084885c0b814000000b900000000480f45c14889c0");
}
#[test]
fn test_merge_add_mov() {
let (mut asm, mut cb) = setup_asm();
let sp = asm.add(CFP, Opnd::UImm(0x40));
asm.mov(CFP, sp); // should be merged to add
asm.compile_with_num_regs(&mut cb, 1);
assert_eq!(format!("{:x}", cb), "4983c540");
}
#[test]
fn test_merge_sub_mov() {
let (mut asm, mut cb) = setup_asm();
let sp = asm.sub(CFP, Opnd::UImm(0x40));
asm.mov(CFP, sp); // should be merged to add
asm.compile_with_num_regs(&mut cb, 1);
assert_eq!(format!("{:x}", cb), "4983ed40");
}
#[test]
fn test_merge_and_mov() {
let (mut asm, mut cb) = setup_asm();
let sp = asm.and(CFP, Opnd::UImm(0x40));
asm.mov(CFP, sp); // should be merged to add
asm.compile_with_num_regs(&mut cb, 1);
assert_eq!(format!("{:x}", cb), "4983e540");
}
#[test]
fn test_merge_or_mov() {
let (mut asm, mut cb) = setup_asm();
let sp = asm.or(CFP, Opnd::UImm(0x40));
asm.mov(CFP, sp); // should be merged to add
asm.compile_with_num_regs(&mut cb, 1);
assert_eq!(format!("{:x}", cb), "4983cd40");
}
#[test]
fn test_merge_xor_mov() {
let (mut asm, mut cb) = setup_asm();
let sp = asm.xor(CFP, Opnd::UImm(0x40));
asm.mov(CFP, sp); // should be merged to add
asm.compile_with_num_regs(&mut cb, 1);
assert_eq!(format!("{:x}", cb), "4983f540");
}
}