summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorywenc <[email protected]>2025-06-30 15:26:23 -0400
committerTakashi Kokubun <[email protected]>2025-06-30 17:04:15 -0700
commit03e08a946d498e75e1bb31ddb28fc012dc4694f5 (patch)
tree7ced9e9cb038754b9d441e31513b484c8fbbc907
parent4a7d1a7062e7802eb6758bab121eecde59b19125 (diff)
ZJIT: Add codegen for IsNil
-rw-r--r--test/ruby/test_zjit.rb9
-rw-r--r--zjit/src/codegen.rs8
2 files changed, 17 insertions, 0 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb
index 823fb8e043..e7ce1e1837 100644
--- a/test/ruby/test_zjit.rb
+++ b/test/ruby/test_zjit.rb
@@ -831,6 +831,15 @@ class TestZJIT < Test::Unit::TestCase
}, call_threshold: 2
end
+ def test_branchnil
+ assert_compiles '[2, nil]', %q{
+ def test(x)
+ x&.succ
+ end
+ [test(1), test(nil)]
+ }, call_threshold: 1, insns: [:branchnil]
+ end
+
# tool/ruby_vm/views/*.erb relies on the zjit instructions a) being contiguous and
# b) being reliably ordered after all the other instructions.
def test_instruction_order
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index 4c1d9698ac..d7d3cb8aca 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -272,6 +272,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
Insn::FixnumLe { left, right } => gen_fixnum_le(asm, opnd!(left), opnd!(right))?,
Insn::FixnumGt { left, right } => gen_fixnum_gt(asm, opnd!(left), opnd!(right))?,
Insn::FixnumGe { left, right } => gen_fixnum_ge(asm, opnd!(left), opnd!(right))?,
+ Insn::IsNil { val } => gen_isnil(asm, opnd!(val))?,
Insn::Test { val } => gen_test(asm, opnd!(val))?,
Insn::GuardType { val, guard_type, state } => gen_guard_type(jit, asm, opnd!(val), *guard_type, &function.frame_state(*state))?,
Insn::GuardBitEquals { val, expected, state } => gen_guard_bit_equals(jit, asm, opnd!(val), *expected, &function.frame_state(*state))?,
@@ -890,6 +891,13 @@ fn gen_fixnum_ge(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Opti
Some(asm.csel_ge(Qtrue.into(), Qfalse.into()))
}
+// Compile val == nil
+fn gen_isnil(asm: &mut Assembler, val: lir::Opnd) -> Option<lir::Opnd> {
+ asm.cmp(val, Qnil.into());
+ // TODO: Implement and use setcc
+ Some(asm.csel_e(Opnd::Imm(1), Opnd::Imm(0)))
+}
+
fn gen_anytostring(asm: &mut Assembler, val: lir::Opnd, str: lir::Opnd, state: &FrameState) -> Option<lir::Opnd> {
// Save PC
gen_save_pc(asm, state);