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:
parent
ce38ad6963
commit
995b960c70
Notes:
git
2023-04-20 17:05:51 +00:00
Merged-By: k0kubun <takashikkbn@gmail.com>
@ -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
|
||||||
|
"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user