YJIT: Merge add/sub/and/or/xor and mov on x86_64 (#7492)
This commit is contained in:
parent
309ff928f5
commit
c7822b8dbb
Notes:
git
2023-03-13 20:33:06 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -166,29 +166,41 @@ impl Assembler
|
|||||||
Insn::And { left, right, out } |
|
Insn::And { left, right, out } |
|
||||||
Insn::Or { left, right, out } |
|
Insn::Or { left, right, out } |
|
||||||
Insn::Xor { left, right, out } => {
|
Insn::Xor { left, right, out } => {
|
||||||
match (unmapped_opnds[0], unmapped_opnds[1]) {
|
match (&left, &right, iterator.peek()) {
|
||||||
(Opnd::Mem(_), Opnd::Mem(_)) => {
|
// Merge this insn, e.g. `add REG, right -> out`, and `mov REG, out` if possible
|
||||||
*left = asm.load(*left);
|
(Opnd::Reg(_), Opnd::UImm(value), Some(Insn::Mov { dest, src }))
|
||||||
*right = asm.load(*right);
|
if out == src && left == dest && live_ranges[index] == index + 1 && uimm_num_bits(*value) <= 32 => {
|
||||||
},
|
*out = *dest;
|
||||||
(Opnd::Mem(_), Opnd::UImm(_) | Opnd::Imm(_)) => {
|
asm.push_insn(insn);
|
||||||
*left = asm.load(*left);
|
iterator.map_insn_index(&mut asm);
|
||||||
},
|
iterator.next_unmapped(); // Pop merged Insn::Mov
|
||||||
// Instruction output whose live range spans beyond this instruction
|
}
|
||||||
(Opnd::InsnOut { idx, .. }, _) => {
|
_ => {
|
||||||
if live_ranges[idx] > index {
|
match (unmapped_opnds[0], unmapped_opnds[1]) {
|
||||||
*left = asm.load(*left);
|
(Opnd::Mem(_), Opnd::Mem(_)) => {
|
||||||
}
|
*left = asm.load(*left);
|
||||||
},
|
*right = asm.load(*right);
|
||||||
// We have to load memory operands to avoid corrupting them
|
},
|
||||||
(Opnd::Mem(_) | Opnd::Reg(_), _) => {
|
(Opnd::Mem(_), Opnd::UImm(_) | Opnd::Imm(_)) => {
|
||||||
*left = asm.load(*left);
|
*left = asm.load(*left);
|
||||||
},
|
},
|
||||||
_ => {}
|
// Instruction output whose live range spans beyond this instruction
|
||||||
};
|
(Opnd::InsnOut { idx, .. }, _) => {
|
||||||
|
if live_ranges[idx] > index {
|
||||||
|
*left = asm.load(*left);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// We have to load memory operands to avoid corrupting them
|
||||||
|
(Opnd::Mem(_) | Opnd::Reg(_), _) => {
|
||||||
|
*left = asm.load(*left);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
*out = asm.next_opnd_out(Opnd::match_num_bits(&[*left, *right]));
|
*out = asm.next_opnd_out(Opnd::match_num_bits(&[*left, *right]));
|
||||||
asm.push_insn(insn);
|
asm.push_insn(insn);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Insn::Cmp { left, right } => {
|
Insn::Cmp { left, right } => {
|
||||||
// Replace `cmp REG, 0` (4 bytes) with `test REG, REG` (3 bytes)
|
// Replace `cmp REG, 0` (4 bytes) with `test REG, REG` (3 bytes)
|
||||||
@ -953,4 +965,59 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(format!("{:x}", cb), "488b43084885c0b814000000b900000000480f45c14889c0");
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user