YJIT: Implement opt_reverse insn (#12175)

This commit is contained in:
Randy Stauner 2024-11-26 14:49:24 -07:00 committed by GitHub
parent 33f15ce80d
commit 8f9b9aecd0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2024-11-26 21:49:46 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
2 changed files with 78 additions and 0 deletions

View File

@ -5309,3 +5309,33 @@ assert_equal '[true, false]', <<~'RUBY'
test("c"),
]
RUBY
# YARV: swap and opt_reverse
assert_equal '["x", "Y", "c", "A", "t", "A", "b", "C", "d"]', <<~'RUBY'
class Swap
def initialize(s)
@a, @b, @c, @d = s.split("")
end
def swap
a, b = @a, @b
b = b.upcase
@a, @b = a, b
end
def reverse_odd
a, b, c = @a, @b, @c
b = b.upcase
@a, @b, @c = a, b, c
end
def reverse_even
a, b, c, d = @a, @b, @c, @d
a = a.upcase
c = c.upcase
@a, @b, @c, @d = a, b, c, d
end
end
Swap.new("xy").swap + Swap.new("cat").reverse_odd + Swap.new("abcd").reverse_even
RUBY

View File

@ -1489,6 +1489,18 @@ fn gen_dupn(
Some(KeepCompiling)
}
// Reverse top X stack entries
fn gen_opt_reverse(
jit: &mut JITState,
asm: &mut Assembler,
) -> Option<CodegenStatus> {
let count = jit.get_arg(0).as_i32();
for n in 0..(count/2) {
stack_swap(asm, n, count - 1 - n);
}
Some(KeepCompiling)
}
// Swap top 2 stack entries
fn gen_swap(
_jit: &mut JITState,
@ -10517,6 +10529,7 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> {
YARVINSN_dup => Some(gen_dup),
YARVINSN_dupn => Some(gen_dupn),
YARVINSN_swap => Some(gen_swap),
YARVINSN_opt_reverse => Some(gen_opt_reverse),
YARVINSN_putnil => Some(gen_putnil),
YARVINSN_putobject => Some(gen_putobject),
YARVINSN_putobject_INT2FIX_0_ => Some(gen_putobject_int2fix),
@ -11093,6 +11106,41 @@ mod tests {
assert!(cb.get_write_pos() > 0); // Write some movs
}
#[test]
fn test_gen_opt_reverse() {
let (_context, mut asm, mut cb, mut ocb) = setup_codegen();
let mut jit = dummy_jit_state(&mut cb, &mut ocb);
// Odd number of elements
asm.stack_push(Type::Fixnum);
asm.stack_push(Type::Flonum);
asm.stack_push(Type::CString);
let mut value_array: [u64; 2] = [0, 3];
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
jit.pc = pc;
let mut status = gen_opt_reverse(&mut jit, &mut asm);
assert_eq!(status, Some(KeepCompiling));
assert_eq!(Type::CString, asm.ctx.get_opnd_type(StackOpnd(2)));
assert_eq!(Type::Flonum, asm.ctx.get_opnd_type(StackOpnd(1)));
assert_eq!(Type::Fixnum, asm.ctx.get_opnd_type(StackOpnd(0)));
// Try again with an even number of elements.
asm.stack_push(Type::Nil);
value_array[1] = 4;
status = gen_opt_reverse(&mut jit, &mut asm);
assert_eq!(status, Some(KeepCompiling));
assert_eq!(Type::Nil, asm.ctx.get_opnd_type(StackOpnd(3)));
assert_eq!(Type::Fixnum, asm.ctx.get_opnd_type(StackOpnd(2)));
assert_eq!(Type::Flonum, asm.ctx.get_opnd_type(StackOpnd(1)));
assert_eq!(Type::CString, asm.ctx.get_opnd_type(StackOpnd(0)));
}
#[test]
fn test_gen_swap() {
let (_context, mut asm, mut cb, mut ocb) = setup_codegen();