ZJIT: Implement codegen for FixnumMod (#14857)

This is mostly to see what happens to the loops-times benchmark.
This commit is contained in:
Max Bernstein 2025-10-20 17:30:48 -04:00 committed by GitHub
parent 6e9f7974df
commit 17368234bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-10-20 21:31:27 +00:00
Merged-By: tekknolagi <donotemailthisaddress@bernsteinbear.com>
10 changed files with 25 additions and 10 deletions

2
depend
View File

@ -7382,8 +7382,10 @@ jit.$(OBJEXT): $(CCAN_DIR)/str/str.h
jit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
jit.$(OBJEXT): $(top_srcdir)/internal/array.h
jit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
jit.$(OBJEXT): $(top_srcdir)/internal/bits.h
jit.$(OBJEXT): $(top_srcdir)/internal/class.h
jit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
jit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
jit.$(OBJEXT): $(top_srcdir)/internal/gc.h
jit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
jit.$(OBJEXT): $(top_srcdir)/internal/namespace.h

7
jit.c
View File

@ -14,6 +14,7 @@
#include "iseq.h"
#include "internal/gc.h"
#include "vm_sync.h"
#include "internal/fixnum.h"
// Field offsets for the RObject struct
enum robject_offsets {
@ -720,3 +721,9 @@ rb_jit_icache_invalidate(void *start, void *end)
#error No instruction cache clear available with this compiler on Aarch64!
#endif
}
VALUE
rb_jit_fix_mod_fix(VALUE recv, VALUE obj)
{
return rb_fix_mod_fix(recv, obj);
}

6
yjit.c
View File

@ -332,12 +332,6 @@ rb_yjit_fix_div_fix(VALUE recv, VALUE obj)
return rb_fix_div_fix(recv, obj);
}
VALUE
rb_yjit_fix_mod_fix(VALUE recv, VALUE obj)
{
return rb_fix_mod_fix(recv, obj);
}
// Return non-zero when `obj` is an array and its last item is a
// `ruby2_keywords` hash. We don't support this kind of splat.
size_t

View File

@ -367,7 +367,7 @@ fn main() {
.allowlist_function("rb_yarv_ary_entry_internal")
.allowlist_function("rb_yjit_ruby2_keywords_splat_p")
.allowlist_function("rb_yjit_fix_div_fix")
.allowlist_function("rb_yjit_fix_mod_fix")
.allowlist_function("rb_jit_fix_mod_fix")
.allowlist_function("rb_FL_TEST")
.allowlist_function("rb_FL_TEST_RAW")
.allowlist_function("rb_RB_TYPE_P")

View File

@ -199,7 +199,7 @@ pub use rb_get_call_data_ci as get_call_data_ci;
pub use rb_yarv_str_eql_internal as rb_str_eql_internal;
pub use rb_yarv_ary_entry_internal as rb_ary_entry_internal;
pub use rb_yjit_fix_div_fix as rb_fix_div_fix;
pub use rb_yjit_fix_mod_fix as rb_fix_mod_fix;
pub use rb_jit_fix_mod_fix as rb_fix_mod_fix;
pub use rb_FL_TEST as FL_TEST;
pub use rb_FL_TEST_RAW as FL_TEST_RAW;
pub use rb_RB_TYPE_P as RB_TYPE_P;

View File

@ -1142,7 +1142,6 @@ extern "C" {
pub fn rb_ary_unshift_m(argc: ::std::os::raw::c_int, argv: *mut VALUE, ary: VALUE) -> VALUE;
pub fn rb_yjit_rb_ary_subseq_length(ary: VALUE, beg: ::std::os::raw::c_long) -> VALUE;
pub fn rb_yjit_fix_div_fix(recv: VALUE, obj: VALUE) -> VALUE;
pub fn rb_yjit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE;
pub fn rb_yjit_ruby2_keywords_splat_p(obj: VALUE) -> usize;
pub fn rb_yjit_splat_varg_checks(
sp: *mut VALUE,
@ -1275,4 +1274,5 @@ extern "C" {
start: *mut ::std::os::raw::c_void,
end: *mut ::std::os::raw::c_void,
);
pub fn rb_jit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE;
}

View File

@ -398,6 +398,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
Insn::FixnumGe { left, right } => gen_fixnum_ge(asm, opnd!(left), opnd!(right)),
Insn::FixnumAnd { left, right } => gen_fixnum_and(asm, opnd!(left), opnd!(right)),
Insn::FixnumOr { left, right } => gen_fixnum_or(asm, opnd!(left), opnd!(right)),
&Insn::FixnumMod { left, right, state } => gen_fixnum_mod(jit, asm, opnd!(left), opnd!(right), &function.frame_state(state)),
Insn::IsNil { val } => gen_isnil(asm, opnd!(val)),
&Insn::IsMethodCfunc { val, cd, cfunc, state: _ } => gen_is_method_cfunc(jit, asm, opnd!(val), cd, cfunc),
&Insn::IsBitEqual { left, right } => gen_is_bit_equal(asm, opnd!(left), opnd!(right)),
@ -447,7 +448,6 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
&Insn::LoadIvarExtended { self_val, id, index } => gen_load_ivar_extended(asm, opnd!(self_val), id, index),
&Insn::ArrayMax { state, .. }
| &Insn::FixnumDiv { state, .. }
| &Insn::FixnumMod { state, .. }
| &Insn::Throw { state, .. }
=> return Err(state),
};
@ -1460,6 +1460,13 @@ fn gen_fixnum_or(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir:
asm.or(left, right)
}
fn gen_fixnum_mod(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd, state: &FrameState) -> lir::Opnd {
// Check for left % 0, which raises ZeroDivisionError
asm.cmp(right, Opnd::from(VALUE::fixnum_from_usize(0)));
asm.je(side_exit(jit, state, FixnumModByZero));
asm_ccall!(asm, rb_fix_mod_fix, left, right)
}
// Compile val == nil
fn gen_isnil(asm: &mut Assembler, val: lir::Opnd) -> lir::Opnd {
asm.cmp(val, Qnil.into());

View File

@ -134,6 +134,7 @@ unsafe extern "C" {
pub fn rb_str_setbyte(str: VALUE, index: VALUE, value: VALUE) -> VALUE;
pub fn rb_str_getbyte(str: VALUE, index: VALUE) -> VALUE;
pub fn rb_vm_splat_array(flag: VALUE, ary: VALUE) -> VALUE;
pub fn rb_jit_fix_mod_fix(x: VALUE, y: VALUE) -> VALUE;
pub fn rb_vm_concat_array(ary1: VALUE, ary2st: VALUE) -> VALUE;
pub fn rb_vm_get_special_object(reg_ep: *const VALUE, value_type: vm_special_object_type) -> VALUE;
pub fn rb_vm_concat_to_array(ary1: VALUE, ary2st: VALUE) -> VALUE;
@ -219,6 +220,7 @@ pub use rb_vm_ci_kwarg as vm_ci_kwarg;
pub use rb_METHOD_ENTRY_VISI as METHOD_ENTRY_VISI;
pub use rb_RCLASS_ORIGIN as RCLASS_ORIGIN;
pub use rb_vm_get_special_object as vm_get_special_object;
pub use rb_jit_fix_mod_fix as rb_fix_mod_fix;
/// Helper so we can get a Rust string for insn_name()
pub fn insn_name(opcode: usize) -> String {

View File

@ -468,6 +468,7 @@ pub enum SideExitReason {
BlockParamProxyModified,
BlockParamProxyNotIseqOrIfunc,
StackOverflow,
FixnumModByZero,
}
#[derive(Debug, Clone, Copy)]

View File

@ -137,6 +137,7 @@ make_counters! {
exit_fixnum_add_overflow,
exit_fixnum_sub_overflow,
exit_fixnum_mult_overflow,
exit_fixnum_mod_by_zero,
exit_guard_type_failure,
exit_guard_type_not_failure,
exit_guard_bit_equals_failure,
@ -332,6 +333,7 @@ pub fn side_exit_counter(reason: crate::hir::SideExitReason) -> Counter {
FixnumAddOverflow => exit_fixnum_add_overflow,
FixnumSubOverflow => exit_fixnum_sub_overflow,
FixnumMultOverflow => exit_fixnum_mult_overflow,
FixnumModByZero => exit_fixnum_mod_by_zero,
GuardType(_) => exit_guard_type_failure,
GuardTypeNot(_) => exit_guard_type_not_failure,
GuardBitEquals(_) => exit_guard_bit_equals_failure,