YJIT: Implement opt_reverse insn (#12175)
This commit is contained in:
parent
33f15ce80d
commit
8f9b9aecd0
Notes:
git
2024-11-26 21:49:46 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -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
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user