YJIT: Avoid splitting mov for small values on arm64 (#7745)

* YJIT: Avoid splitting mov for small values on arm64

* Fix a comment

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>

* YJIT: Test the 0xffff boundary

---------

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
This commit is contained in:
Takashi Kokubun 2023-04-20 10:05:30 -07:00 committed by GitHub
parent ce38ad6963
commit 995b960c70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
Notes: git 2023-04-20 17:05:51 +00:00
Merged-By: k0kubun <takashikkbn@gmail.com>
2 changed files with 32 additions and 3 deletions

View File

@ -605,7 +605,11 @@ impl Assembler
}, },
// Otherwise we'll use the normal mov instruction. // Otherwise we'll use the normal mov instruction.
(Opnd::Reg(_), _) => { (Opnd::Reg(_), _) => {
let value = split_bitmask_immediate(asm, src, dest.rm_num_bits()); let value = match src {
// Unlike other instructions, we can avoid splitting this case, using movz.
Opnd::UImm(uimm) if uimm <= 0xffff => src,
_ => split_bitmask_immediate(asm, src, dest.rm_num_bits()),
};
asm.mov(dest, value); asm.mov(dest, value);
}, },
_ => unreachable!() _ => unreachable!()
@ -956,7 +960,18 @@ impl Assembler
}; };
}, },
Insn::Mov { dest, src } => { Insn::Mov { dest, src } => {
// This supports the following two kinds of immediates:
// * The value fits into a single movz instruction
// * It can be encoded with the special bitmask immediate encoding
// arm64_split() should have split other immediates that require multiple instructions.
match src {
Opnd::UImm(uimm) if *uimm <= 0xffff => {
movz(cb, dest.into(), A64Opnd::new_uimm(*uimm), 0);
},
_ => {
mov(cb, dest.into(), src.into()); mov(cb, dest.into(), src.into());
}
}
}, },
Insn::Lea { opnd, out } => { Insn::Lea { opnd, out } => {
let opnd: A64Opnd = opnd.into(); let opnd: A64Opnd = opnd.into();
@ -1588,4 +1603,18 @@ mod tests {
0x0: ldur x1, [x19, #8] 0x0: ldur x1, [x19, #8]
"}); "});
} }
#[test]
fn test_not_split_mov() {
let (mut asm, mut cb) = setup_asm();
asm.mov(Opnd::Reg(Assembler::TEMP_REGS[0]), Opnd::UImm(0xffff));
asm.mov(Opnd::Reg(Assembler::TEMP_REGS[0]), Opnd::UImm(0x10000));
asm.compile_with_num_regs(&mut cb, 1);
assert_disasm!(cb, "e1ff9fd2e10370b2", {"
0x0: mov x1, #0xffff
0x4: orr x1, xzr, #0x10000
"});
}
} }

View File

@ -207,7 +207,6 @@ pub fn disasm_addr_range(cb: &CodeBlock, start_addr: usize, end_addr: usize) ->
#[cfg(test)] #[cfg(test)]
macro_rules! assert_disasm { macro_rules! assert_disasm {
($cb:expr, $hex:expr, $disasm:expr) => { ($cb:expr, $hex:expr, $disasm:expr) => {
assert_eq!(format!("{:x}", $cb), $hex);
#[cfg(feature = "disasm")] #[cfg(feature = "disasm")]
{ {
let disasm = disasm_addr_range( let disasm = disasm_addr_range(
@ -217,6 +216,7 @@ macro_rules! assert_disasm {
); );
assert_eq!(unindent(&disasm, false), unindent(&$disasm, true)); assert_eq!(unindent(&disasm, false), unindent(&$disasm, true));
} }
assert_eq!(format!("{:x}", $cb), $hex);
}; };
} }
#[cfg(test)] #[cfg(test)]