From 8c401de5d90f33d7afecb813737a1f2924a5f096 Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 1 Oct 2016 10:19:36 +0000 Subject: [PATCH] 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 --- ChangeLog | 7 ++++ compile.c | 80 ++++++++++++++++++++---------------------- test/ruby/test_flip.rb | 3 ++ 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 728efe5c6d..b6259ca559 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sat Oct 1 19:19:34 2016 Nobuyoshi Nakada + + * 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 * win32/win32.c (poll_child_status): rb_w32_wait_events_blocking() sets diff --git a/compile.c b/compile.c index 72181d3b9f..674ae70068 100644 --- a/compile.c +++ b/compile.c @@ -2786,6 +2786,39 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node) return COMPILE_OK; } +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