summaryrefslogtreecommitdiff
path: root/yjit
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-04-19 17:25:24 -0700
committerGitHub <noreply@github.com>2023-04-19 17:25:24 -0700
commitd2d0954c1618d90587f6f4804d9db0af0ef24ee1 (patch)
tree9807fdd3bb097d852fe068e28abd937ca0ba0b20 /yjit
parent5fc11f306c6d38e46cc45f0ffabc5ea14084a11a (diff)
downloadruby-d2d0954c1618d90587f6f4804d9db0af0ef24ee1.tar.gz
YJIT: Replace Mov with LoadInto on arm64 (#7744)
* YJIT: Replace Mov with LoadInto on arm64 * YJIT: Add a test for the new pass
Diffstat (limited to 'yjit')
-rw-r--r--yjit/src/backend/arm64/mod.rs59
1 files changed, 39 insertions, 20 deletions
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]
+ "});
+ }
}