insns.def: optimize & and | of Integer [experimental]

not optimizing Array#& and Array#| because vm_insnhelper.c can't easily
inline it (large amount of array.c code would be needed in vm_insnhelper.c)
and the method body is a little complicated compared to Integer's ones.
So I thought only Integer#& and Integer#| have a significant impact,
and eliminating unnecessary branches would contribute to JIT's performance.

vm_insnhelper.c: ditto

tool/transform_mjit_header.rb: make sure these instructions are inlined
on JIT.

compile.c: compile vm_opt_and and vm_opt_or.
id.def: define id for them to be used in compile.c and vm*.c
vm.c: track redefinition of Integer#& and Integer#|
vm_core.h: allow detecting redefinition of & and |

test/ruby/test_jit.rb: test new insns
test/ruby/test_optimization.rb: ditto

* Optcarrot benchmark

This is a kind of experimental thing but I'm committing this since the
performance impact is significant especially on Optcarrot with JIT.

$ benchmark-driver benchmark.yml --rbenv 'before::before --disable-gems;before+JIT::before --disable-gems --jit;after::after --disable-gems;after+JIT::after --disable-gems --jit' -v --repeat-count 24
before: ruby 2.6.0dev (2018-09-24 trunk 64821) [x86_64-linux]
before+JIT: ruby 2.6.0dev (2018-09-24 trunk 64821) +JIT [x86_64-linux]
after: ruby 2.6.0dev (2018-09-24 opt_and 64821) [x86_64-linux]
last_commit=opt_or
after+JIT: ruby 2.6.0dev (2018-09-24 opt_and 64821) +JIT [x86_64-linux]
last_commit=opt_or
Calculating -------------------------------------
                             before  before+JIT       after   after+JIT
Optcarrot Lan_Master.nes     51.460      66.315      53.023      71.173 fps

Comparison:
             Optcarrot Lan_Master.nes
               after+JIT:        71.2 fps
              before+JIT:        66.3 fps - 1.07x  slower
                   after:        53.0 fps - 1.34x  slower
                  before:        51.5 fps - 1.38x  slower

[close https://github.com/ruby/ruby/pull/1963]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64824 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
k0kubun 2018-09-24 12:40:28 +00:00
parent 1aef602d5a
commit fb80f6c7ba
9 changed files with 80 additions and 0 deletions

View File

@ -3245,6 +3245,8 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
case idGE: SP_INSN(ge); return COMPILE_OK;
case idLTLT: SP_INSN(ltlt); return COMPILE_OK;
case idAREF: SP_INSN(aref); return COMPILE_OK;
case idAnd: SP_INSN(and); return COMPILE_OK;
case idOr: SP_INSN(or); return COMPILE_OK;
}
break;
case 2:

View File

@ -97,6 +97,8 @@ token_ops = %[\
Eqq === EQQ
Neq != NEQ
Not !
And &
Or |
Backquote `
EqTilde =~ MATCH
NeqTilde !~ NMATCH

View File

@ -1216,6 +1216,34 @@ opt_ltlt
}
}
/* optimized X&Y. */
DEFINE_INSN
opt_and
(CALL_INFO ci, CALL_CACHE cc)
(VALUE recv, VALUE obj)
(VALUE val)
{
val = vm_opt_and(recv, obj);
if (val == Qundef) {
CALL_SIMPLE_METHOD();
}
}
/* optimized X|Y. */
DEFINE_INSN
opt_or
(CALL_INFO ci, CALL_CACHE cc)
(VALUE recv, VALUE obj)
(VALUE val)
{
val = vm_opt_or(recv, obj);
if (val == Qundef) {
CALL_SIMPLE_METHOD();
}
}
/* [] */
DEFINE_INSN
opt_aref

View File

@ -478,6 +478,14 @@ class TestJIT < Test::Unit::TestCase
assert_compile_once('[1] << 2', result_inspect: '[1, 2]', insns: %i[opt_ltlt])
end
def test_compile_insn_opt_and
assert_compile_once('1 & 3', result_inspect: '1', insns: %i[opt_and])
end
def test_compile_insn_opt_or
assert_compile_once('1 | 3', result_inspect: '3', insns: %i[opt_or])
end
def test_compile_insn_opt_aref
skip_on_mswin
# optimized call (optimized JIT) -> send call

View File

@ -187,6 +187,16 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_redefine_method('String', '<<', 'assert_equal "b", "a" << "b"')
end
def test_fixnum_and
assert_equal 1, 1&3
assert_redefine_method('Integer', '&', 'assert_equal 3, 1&3')
end
def test_fixnum_or
assert_equal 3, 1|3
assert_redefine_method('Integer', '|', 'assert_equal 1, 3|1')
end
def test_array_plus
assert_equal [1,2], [1]+[2]
assert_redefine_method('Array', '+', 'assert_equal [2], [1]+[2]')

View File

@ -52,6 +52,8 @@ module MJITHeader
'vm_opt_gt',
'vm_opt_ge',
'vm_opt_ltlt',
'vm_opt_and',
'vm_opt_or',
'vm_opt_aref',
'vm_opt_aset',
'vm_opt_aref_with',

2
vm.c
View File

@ -1610,6 +1610,8 @@ vm_init_redefined_flag(void)
OP(Max, MAX), (C(Array));
OP(Min, MIN), (C(Array));
OP(Call, CALL), (C(Proc));
OP(And, AND), (C(Integer));
OP(Or, OR), (C(Integer));
#undef C
#undef OP
}

View File

@ -531,6 +531,8 @@ enum ruby_basic_operators {
BOP_MAX,
BOP_MIN,
BOP_CALL,
BOP_AND,
BOP_OR,
BOP_LAST_
};

View File

@ -3652,6 +3652,30 @@ vm_opt_ltlt(VALUE recv, VALUE obj)
}
}
static VALUE
vm_opt_and(VALUE recv, VALUE obj)
{
if (FIXNUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
return LONG2NUM(FIX2LONG(recv) & FIX2LONG(obj));
}
else {
return Qundef;
}
}
static VALUE
vm_opt_or(VALUE recv, VALUE obj)
{
if (FIXNUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_OR, INTEGER_REDEFINED_OP_FLAG)) {
return LONG2NUM(FIX2LONG(recv) | FIX2LONG(obj));
}
else {
return Qundef;
}
}
static VALUE
vm_opt_aref(VALUE recv, VALUE obj)
{