ruby-changes:73172
From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 00:57:59 +0900 (JST)
Subject: [ruby-changes:73172] e1f3f038e9 (master): Fix jumps (https://github.com/Shopify/ruby/pull/309)
https://git.ruby-lang.org/ruby.git/commit/?id=e1f3f038e9 From e1f3f038e93d5b36ed6e6a15feac478bf3cfe1fa Mon Sep 17 00:00:00 2001 From: Kevin Newton <kddnewton@g...> Date: Fri, 8 Jul 2022 16:35:51 -0400 Subject: Fix jumps (https://github.com/Shopify/ruby/pull/309) * Jumps for A64 should be in # of instructions * More splitting for Arm64 https://github.com/Shopify/ruby/pull/309 --- yjit/src/backend/arm64/mod.rs | 56 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs index 7e6a187f8f..0fee18c068 100644 --- a/yjit/src/backend/arm64/mod.rs +++ b/yjit/src/backend/arm64/mod.rs @@ -140,6 +140,14 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L140 asm.incr_counter(new_opnds[0], new_opnds[1]); }, + Op::JmpOpnd => { + if let Opnd::Mem(_) = opnds[0] { + let opnd0 = asm.load(opnds[0]); + asm.jmp_opnd(opnd0); + } else { + asm.jmp_opnd(opnds[0]); + } + }, Op::Mov => { // The value that is being moved must be either a register // or an immediate that can be encoded as a bitmask @@ -150,7 +158,15 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L158 Opnd::Mem(_) | Opnd::Imm(_) => asm.load(opnds[1]), Opnd::UImm(uimm) => { if let Ok(encoded) = BitmaskImmediate::try_from(uimm) { - opnds[1] + if let Opnd::Mem(_) = opnds[0] { + // 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. + asm.load(opnds[1]) + } else { + opnds[1] + } } else { asm.load(opnds[1]) } @@ -158,9 +174,9 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L174 _ => unreachable!() }; - /// 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. + // 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 opnds[0] { Opnd::Mem(_) => asm.store(opnds[0], value), _ => asm.mov(opnds[0], value) @@ -207,6 +223,26 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L223 /// Returns a list of GC offsets pub fn arm64_emit(&mut self, cb: &mut CodeBlock) -> Vec<u32> { + /// Determine how many instructions it will take to represent moving + /// this value into a register. Note that the return value of this + /// function must correspond to how many instructions are used to + /// represent this load in the emit_load_value function. + fn emit_load_size(value: u64) -> u8 { + if BitmaskImmediate::try_from(value).is_ok() { + return 1; + } + + if value < (1 << 16) { + 1 + } else if value < (1 << 32) { + 2 + } else if value < (1 << 48) { + 3 + } else { + 4 + } + } + /// Emit the required instructions to load the given value into the /// given register. Our goal here is to use as few instructions as /// possible to get this value into the register. @@ -275,7 +311,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L311 // If we get to this instruction, then the condition // wasn't met, in which case we'll jump past the // next instruction that performs the direct jump. - b(cb, A64Opnd::new_imm(4)); + b(cb, A64Opnd::new_imm(1)); // Here we'll perform the direct jump to the target. b(cb, A64Opnd::new_imm(offset / 4)); @@ -283,8 +319,10 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L319 // If we get to this instruction, then the condition // wasn't met, in which case we'll jump past the // next instruction that perform the direct jump. - b(cb, A64Opnd::new_imm(8)); - emit_load_value(cb, X29, dst_addr as u64); + let value = dst_addr as u64; + + b(cb, A64Opnd::new_imm(emit_load_size(value).into())); + emit_load_value(cb, X29, value); br(cb, X29); } } @@ -392,10 +430,10 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L430 }, Op::CPush => { add(cb, C_SP_REG, C_SP_REG, C_SP_STEP); - mov(cb, A64Opnd::new_mem(64, C_SP_REG, 0), insn.opnds[0].into()); + stur(cb, insn.opnds[0].into(), A64Opnd::new_mem(64, C_SP_REG, 0)); }, Op::CPop => { - mov(cb, insn.out.into(), A64Opnd::new_mem(64, C_SP_REG, 0)); + ldur(cb, insn.opnds[0].into(), A64Opnd::new_mem(64, C_SP_REG, 0)); sub(cb, C_SP_REG, C_SP_REG, C_SP_STEP); }, Op::CCall => { -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/