diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-10-01 10:19:36 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-10-01 10:19:36 +0000 |
commit | 813166b2294d47cd5c2357f3253c53ac3e500ab8 (patch) | |
tree | d8e06388e7158e5bfdfe00e6eaa2483d787a2bc8 | |
parent | 7b28db580f849220324dc614381fee27c3a8c35d (diff) | |
download | ruby-813166b2294d47cd5c2357f3253c53ac3e500ab8.tar.gz |
compile.c: optimize flip-flop
* compile.c (compile_flip_flop): simplify generated code.
* compile.c (compile_branch_condition): flip-flop can appear only
in coditional expressions.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | compile.c | 80 | ||||
-rw-r--r-- | test/ruby/test_flip.rb | 3 |
3 files changed, 49 insertions, 41 deletions
@@ -1,3 +1,10 @@ +Sat Oct 1 19:19:34 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * compile.c (compile_flip_flop): simplify generated code. + + * compile.c (compile_branch_condition): flip-flop can appear only + in coditional expressions. + Sat Oct 1 02:02:02 2016 NAKAMURA Usaku <usa@ruby-lang.org> * win32/win32.c (poll_child_status): rb_w32_wait_events_blocking() sets @@ -2787,6 +2787,39 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node) } static int +compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int again, + LABEL *then_label, LABEL *else_label) +{ + const int line = nd_line(node); + LABEL *lend = NEW_LABEL(line); + rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(iseq->body->local_iseq) + + VM_SVAR_FLIPFLOP_START; + VALUE key = INT2FIX(cnt); + + ADD_INSN2(ret, line, getspecial, key, INT2FIX(0)); + ADD_INSNL(ret, line, branchif, lend); + + /* *flip == 0 */ + COMPILE(ret, "flip2 beg", node->nd_beg); + ADD_INSNL(ret, line, branchunless, else_label); + ADD_INSN1(ret, line, putobject, Qtrue); + ADD_INSN1(ret, line, setspecial, key); + if (!again) { + ADD_INSNL(ret, line, jump, then_label); + } + + /* *flip == 1 */ + ADD_LABEL(ret, lend); + COMPILE(ret, "flip2 end", node->nd_end); + ADD_INSNL(ret, line, branchunless, then_label); + ADD_INSN1(ret, line, putobject, Qfalse); + ADD_INSN1(ret, line, setspecial, key); + ADD_INSNL(ret, line, jump, then_label); + + return COMPILE_OK; +} + +static int compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond, LABEL *then_label, LABEL *else_label) { @@ -2834,6 +2867,12 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond, /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ ADD_INSNL(ret, nd_line(cond), jump, else_label); break; + case NODE_FLIP2: + compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label); + break; + case NODE_FLIP3: + compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label); + break; default: COMPILE(ret, "branch condition", cond); ADD_INSNL(ret, nd_line(cond), branchunless, else_label); @@ -5896,47 +5935,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } break; } - case NODE_FLIP2: - case NODE_FLIP3:{ - LABEL *lend = NEW_LABEL(line); - LABEL *lfin = NEW_LABEL(line); - LABEL *ltrue = NEW_LABEL(line); - rb_iseq_t *local_iseq = iseq->body->local_iseq; - rb_num_t cnt; - VALUE key; - - cnt = ISEQ_FLIP_CNT_INCREMENT(local_iseq) + VM_SVAR_FLIPFLOP_START; - key = INT2FIX(cnt); - - ADD_INSN2(ret, line, getspecial, key, INT2FIX(0)); - ADD_INSNL(ret, line, branchif, lend); - - /* *flip == 0 */ - COMPILE(ret, "flip2 beg", node->nd_beg); - ADD_INSN(ret, line, dup); - ADD_INSNL(ret, line, branchunless, lfin); - if (nd_type(node) == NODE_FLIP3) { - ADD_INSN(ret, line, dup); - ADD_INSN1(ret, line, setspecial, key); - ADD_INSNL(ret, line, jump, lfin); - } - else { - ADD_INSN1(ret, line, setspecial, key); - } - - /* *flip == 1 */ - ADD_LABEL(ret, lend); - COMPILE(ret, "flip2 end", node->nd_end); - ADD_INSNL(ret, line, branchunless, ltrue); - ADD_INSN1(ret, line, putobject, Qfalse); - ADD_INSN1(ret, line, setspecial, key); - - ADD_LABEL(ret, ltrue); - ADD_INSN1(ret, line, putobject, Qtrue); - - ADD_LABEL(ret, lfin); - break; - } case NODE_SELF:{ if (!poped) { ADD_INSN(ret, line, putself); diff --git a/test/ruby/test_flip.rb b/test/ruby/test_flip.rb index 11f387d7ac..7c805574a8 100644 --- a/test/ruby/test_flip.rb +++ b/test/ruby/test_flip.rb @@ -3,8 +3,11 @@ require 'test/unit' class TestFlip < Test::Unit::TestCase def test_flip_flop + assert_equal [4,5], (1..9).select {|n| true if (n==4)..(n==5)} + assert_equal [4,5], (1..9).select {|n| true if (n==4)...(n==5)} assert_equal [2], (1..9).select {|n| true if (n==2)..(n%2).zero?} assert_equal [2,3,4], (1..9).select {|n| true if (n==2)...(n%2).zero?} + assert_equal [4,5,7,8], (1..9).select {|n| true if (n==4)...(n==5) or (n==7)...(n==8)} end def test_hidden_key |