diff options
-rw-r--r-- | compile.c | 12 | ||||
-rw-r--r-- | test/ruby/test_optimization.rb | 13 |
2 files changed, 22 insertions, 3 deletions
@@ -2730,12 +2730,13 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal ELEM_INSERT_NEXT(&dniobj->link, &pop->link); goto again; } - else if (IS_INSN(iobj->link.prev) && - (piobj = (INSN *)iobj->link.prev) && + else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 && (IS_INSN_ID(piobj, branchif) || IS_INSN_ID(piobj, branchunless))) { INSN *pdiobj = (INSN *)get_destination_insn(piobj); if (niobj == pdiobj) { + int refcnt = IS_LABEL(piobj->link.next) ? + ((LABEL *)piobj->link.next)->refcnt : 0; /* * useless jump elimination (if/unless destination): * if L1 @@ -2753,7 +2754,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal piobj->insn_id = (IS_INSN_ID(piobj, branchif)) ? BIN(branchunless) : BIN(branchif); replace_destination(piobj, iobj); - ELEM_REMOVE(&iobj->link); + if (refcnt <= 1) { + ELEM_REMOVE(&iobj->link); + } + else { + /* TODO: replace other branch destinations too */ + } return COMPILE_OK; } else if (diobj == pdiobj) { diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 32bdcef13d..d4a1fdbcea 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -771,4 +771,17 @@ class TestRubyOptimization < Test::Unit::TestCase tap {true || tap {}} end; end + + def test_jump_elimination_with_optimized_out_block + x = Object.new + def x.bug(obj) + if obj || obj + obj = obj + else + raise "[ruby-core:87830] [Bug #14897]" + end + obj + end + assert_equal(:ok, x.bug(:ok)) + end end |