summaryrefslogtreecommitdiff
path: root/lib/ruby_vm/mjit/insn_compiler.rb
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2023-02-13 21:48:24 -0800
committerTakashi Kokubun <[email protected]>2023-03-05 23:28:59 -0800
commit51d36c7b34c898c19dff578e665fa0bf1a3cff01 (patch)
tree8b4b332c2594006419df5b2a167fad1eae5782f2 /lib/ruby_vm/mjit/insn_compiler.rb
parent1b0fbd137fb4fa07e1a67fcf75302a80afac0c50 (diff)
Implement opt_le, opt_ge, and opt_gt
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/7448
Diffstat (limited to 'lib/ruby_vm/mjit/insn_compiler.rb')
-rw-r--r--lib/ruby_vm/mjit/insn_compiler.rb123
1 files changed, 72 insertions, 51 deletions
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb
index 49f88db391..dd00ff3e39 100644
--- a/lib/ruby_vm/mjit/insn_compiler.rb
+++ b/lib/ruby_vm/mjit/insn_compiler.rb
@@ -23,7 +23,7 @@ module RubyVM::MJIT
asm.incr_counter(:mjit_insns_count)
asm.comment("Insn: #{insn.name}")
- # 31/101
+ # 34/101
case insn.name
when :nop then nop(jit, ctx, asm)
# getlocal
@@ -101,9 +101,9 @@ module RubyVM::MJIT
# opt_eq
# opt_neq
when :opt_lt then opt_lt(jit, ctx, asm)
- # opt_le
- # opt_gt
- # opt_ge
+ when :opt_le then opt_le(jit, ctx, asm)
+ when :opt_gt then opt_gt(jit, ctx, asm)
+ when :opt_ge then opt_ge(jit, ctx, asm)
when :opt_ltlt then opt_ltlt(jit, ctx, asm)
# opt_and
# opt_or
@@ -574,51 +574,29 @@ module RubyVM::MJIT
# @param ctx [RubyVM::MJIT::Context]
# @param asm [RubyVM::MJIT::Assembler]
def opt_lt(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- comptime_recv = jit.peek_at_stack(1)
- comptime_obj = jit.peek_at_stack(0)
-
- if fixnum?(comptime_recv) && fixnum?(comptime_obj)
- # Generate a side exit before popping operands
- side_exit = side_exit(jit, ctx)
-
- unless Invariants.assume_bop_not_redefined(jit, C.INTEGER_REDEFINED_OP_FLAG, C.BOP_LT)
- return CantCompile
- end
-
- obj_opnd = ctx.stack_pop
- recv_opnd = ctx.stack_pop
-
- asm.comment('guard recv is fixnum') # TODO: skip this with type information
- asm.test(recv_opnd, C.RUBY_FIXNUM_FLAG)
- asm.jz(side_exit)
-
- asm.comment('guard obj is fixnum') # TODO: skip this with type information
- asm.test(obj_opnd, C.RUBY_FIXNUM_FLAG)
- asm.jz(side_exit)
-
- asm.mov(:rax, obj_opnd)
- asm.cmp(recv_opnd, :rax)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmovl(:rax, :rcx)
+ jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovl, bop: C.BOP_LT)
+ end
- dst_opnd = ctx.stack_push
- asm.mov(dst_opnd, :rax)
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def opt_le(jit, ctx, asm)
+ jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovle, bop: C.BOP_LE)
+ end
- KeepCompiling
- else
- opt_send_without_block(jit, ctx, asm)
- end
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def opt_gt(jit, ctx, asm)
+ jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovg, bop: C.BOP_GT)
end
- # opt_le
- # opt_gt
- # opt_ge
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def opt_ge(jit, ctx, asm)
+ jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovge, bop: C.BOP_GE)
+ end
# @param jit [RubyVM::MJIT::JITState]
# @param ctx [RubyVM::MJIT::Context]
@@ -819,12 +797,7 @@ module RubyVM::MJIT
# @param ctx [RubyVM::MJIT::Context]
# @param asm [RubyVM::MJIT::Assembler]
def jit_chain_guard(opcode, jit, ctx, asm, side_exit, limit: 10)
- case opcode
- when :je, :jne, :jnz, :jz
- # ok
- else
- raise ArgumentError, "jit_chain_guard: unexpected opcode #{opcode.inspect}"
- end
+ opcode => :je | :jne | :jnz | :jz
if ctx.chain_depth < limit
deeper = ctx.dup
@@ -913,6 +886,54 @@ module RubyVM::MJIT
# @param jit [RubyVM::MJIT::JITState]
# @param ctx [RubyVM::MJIT::Context]
# @param asm [RubyVM::MJIT::Assembler]
+ def jit_fixnum_cmp(jit, ctx, asm, opcode:, bop:)
+ opcode => :cmovl | :cmovle | :cmovg | :cmovge
+
+ unless jit.at_current_insn?
+ defer_compilation(jit, ctx, asm)
+ return EndBlock
+ end
+
+ comptime_recv = jit.peek_at_stack(1)
+ comptime_obj = jit.peek_at_stack(0)
+
+ if fixnum?(comptime_recv) && fixnum?(comptime_obj)
+ # Generate a side exit before popping operands
+ side_exit = side_exit(jit, ctx)
+
+ unless Invariants.assume_bop_not_redefined(jit, C.INTEGER_REDEFINED_OP_FLAG, bop)
+ return CantCompile
+ end
+
+ obj_opnd = ctx.stack_pop
+ recv_opnd = ctx.stack_pop
+
+ asm.comment('guard recv is fixnum') # TODO: skip this with type information
+ asm.test(recv_opnd, C.RUBY_FIXNUM_FLAG)
+ asm.jz(side_exit)
+
+ asm.comment('guard obj is fixnum') # TODO: skip this with type information
+ asm.test(obj_opnd, C.RUBY_FIXNUM_FLAG)
+ asm.jz(side_exit)
+
+ asm.mov(:rax, obj_opnd)
+ asm.cmp(recv_opnd, :rax)
+ asm.mov(:rax, Qfalse)
+ asm.mov(:rcx, Qtrue)
+ asm.public_send(opcode, :rax, :rcx)
+
+ dst_opnd = ctx.stack_push
+ asm.mov(dst_opnd, :rax)
+
+ KeepCompiling
+ else
+ opt_send_without_block(jit, ctx, asm)
+ end
+ end
+
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
def jit_prepare_routine_call(jit, ctx, asm)
jit_save_pc(jit, asm)
jit_save_sp(jit, ctx, asm)