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 коммит произвёл GitHub
Родитель ce38ad6963
Коммит 995b960c70
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 32 добавлений и 3 удалений

Просмотреть файл

@ -605,7 +605,11 @@ impl Assembler
},
// Otherwise we'll use the normal mov instruction.
(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);
},
_ => unreachable!()
@ -956,7 +960,18 @@ impl Assembler
};
},
Insn::Mov { dest, src } => {
mov(cb, dest.into(), src.into());
// 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());
}
}
},
Insn::Lea { opnd, out } => {
let opnd: A64Opnd = opnd.into();
@ -1588,4 +1603,18 @@ mod tests {
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
"});
}
}

Просмотреть файл

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