From d2d0954c1618d90587f6f4804d9db0af0ef24ee1 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 19 Apr 2023 17:25:24 -0700 Subject: YJIT: Replace Mov with LoadInto on arm64 (#7744) * YJIT: Replace Mov with LoadInto on arm64 * YJIT: Add a test for the new pass --- yjit/src/backend/arm64/mod.rs | 59 ++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 20 deletions(-) (limited to 'yjit/src') diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs index ee7e0edfa6..928406a956 100644 --- a/yjit/src/backend/arm64/mod.rs +++ b/yjit/src/backend/arm64/mod.rs @@ -575,30 +575,37 @@ impl Assembler }; }, Insn::Mov { dest, src } => { - let value: Opnd = match (dest, src) { - // If the first operand is zero, then we can just use - // the zero register. - (Opnd::Mem(_), Opnd::UImm(0) | Opnd::Imm(0)) => Opnd::Reg(XZR_REG), - // If the first operand is a memory operand, we're going - // to transform this into a store instruction, so we'll - // need to load this anyway. - (Opnd::Mem(_), Opnd::UImm(_)) => asm.load(src), - // The value that is being moved must be either a - // register or an immediate that can be encoded as a - // bitmask immediate. Otherwise, we'll need to split the - // move into multiple instructions. - _ => split_bitmask_immediate(asm, src, dest.rm_num_bits()) - }; + match (dest, src) { + // If we're attempting to load into a memory operand, then + // we'll switch over to the store instruction. + (Opnd::Mem(_), _) => { + let value = match src { + // If the first operand is zero, then we can just use + // the zero register. + Opnd::UImm(0) | Opnd::Imm(0) => Opnd::Reg(XZR_REG), + // If the first operand is a memory operand, we're going + // to transform this into a store instruction, so we'll + // need to load this anyway. + Opnd::UImm(_) => asm.load(src), + // The value that is being moved must be either a + // register or an immediate that can be encoded as a + // bitmask immediate. Otherwise, we'll need to split the + // move into multiple instructions. + _ => split_bitmask_immediate(asm, src, dest.rm_num_bits()) + }; - // If we're attempting to load into a memory operand, then - // we'll switch over to the store instruction. Otherwise - // we'll use the normal mov instruction. - match dest { - Opnd::Mem(_) => { let opnd0 = split_memory_address(asm, dest); asm.store(opnd0, value); }, - Opnd::Reg(_) => { + // If we're loading a memory operand into a register, then + // we'll switch over to the load instruction. + (Opnd::Reg(_), Opnd::Mem(_)) => { + let value = split_memory_address(asm, src); + asm.load_into(dest, value); + }, + // Otherwise we'll use the normal mov instruction. + (Opnd::Reg(_), _) => { + let value = split_bitmask_immediate(asm, src, dest.rm_num_bits()); asm.mov(dest, value); }, _ => unreachable!() @@ -1569,4 +1576,16 @@ mod tests { )), } } + + #[test] + fn test_replace_mov_with_ldur() { + let (mut asm, mut cb) = setup_asm(); + + asm.mov(Opnd::Reg(Assembler::TEMP_REGS[0]), Opnd::mem(64, CFP, 8)); + asm.compile_with_num_regs(&mut cb, 1); + + assert_disasm!(cb, "618240f8", {" + 0x0: ldur x1, [x19, #8] + "}); + } } -- cgit v1.2.1