[Bug #20572] Abandon if replacing destination is the same

This commit is contained in:
Nobuyoshi Nakada 2024-06-12 19:03:33 +09:00
parent 278a7cb057
commit 32a555ea53
No known key found for this signature in database
GPG Key ID: 3582D74E1FEE4465
2 changed files with 18 additions and 8 deletions

View File

@ -2972,16 +2972,18 @@ unref_destination(INSN *iobj, int pos)
if (!lobj->refcnt) ELEM_REMOVE(&lobj->link); if (!lobj->refcnt) ELEM_REMOVE(&lobj->link);
} }
static void static bool
replace_destination(INSN *dobj, INSN *nobj) replace_destination(INSN *dobj, INSN *nobj)
{ {
VALUE n = OPERAND_AT(nobj, 0); VALUE n = OPERAND_AT(nobj, 0);
LABEL *dl = (LABEL *)OPERAND_AT(dobj, 0); LABEL *dl = (LABEL *)OPERAND_AT(dobj, 0);
LABEL *nl = (LABEL *)n; LABEL *nl = (LABEL *)n;
if (dl == nl) return false;
--dl->refcnt; --dl->refcnt;
++nl->refcnt; ++nl->refcnt;
OPERAND_AT(dobj, 0) = n; OPERAND_AT(dobj, 0) = n;
if (!dl->refcnt) ELEM_REMOVE(&dl->link); if (!dl->refcnt) ELEM_REMOVE(&dl->link);
return true;
} }
static LABEL* static LABEL*
@ -3263,10 +3265,11 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* => in this case, first jump instruction should jump to * => in this case, first jump instruction should jump to
* LABEL2 directly * LABEL2 directly
*/ */
replace_destination(iobj, diobj); if (replace_destination(iobj, diobj)) {
remove_unreachable_chunk(iseq, iobj->link.next); remove_unreachable_chunk(iseq, iobj->link.next);
goto again; goto again;
} }
}
else if (IS_INSN_ID(diobj, leave)) { else if (IS_INSN_ID(diobj, leave)) {
/* /*
* jump LABEL * jump LABEL
@ -3310,8 +3313,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
*/ */
piobj->insn_id = (IS_INSN_ID(piobj, branchif)) piobj->insn_id = (IS_INSN_ID(piobj, branchif))
? BIN(branchunless) : BIN(branchif); ? BIN(branchunless) : BIN(branchif);
replace_destination(piobj, iobj); if (replace_destination(piobj, iobj) && refcnt <= 1) {
if (refcnt <= 1) {
ELEM_REMOVE(&iobj->link); ELEM_REMOVE(&iobj->link);
} }
else { else {
@ -3440,7 +3442,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
for (;;) { for (;;) {
if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) { if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) {
replace_destination(iobj, nobj); if (!replace_destination(iobj, nobj)) break;
} }
else if (prev_dup && IS_INSN_ID(nobj, dup) && else if (prev_dup && IS_INSN_ID(nobj, dup) &&
!!(nobj = (INSN *)nobj->link.next) && !!(nobj = (INSN *)nobj->link.next) &&
@ -3461,7 +3463,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* dup * dup
* if L2 * if L2
*/ */
replace_destination(iobj, nobj); if (!replace_destination(iobj, nobj)) break;
} }
else if (pobj) { else if (pobj) {
/* /*

View File

@ -871,4 +871,12 @@ class TestISeq < Test::Unit::TestCase
RubyVM::InstructionSequence.load_from_binary(var_0) RubyVM::InstructionSequence.load_from_binary(var_0)
end end
end end
def test_while_in_until_condition
assert_in_out_err(["--dump=i", "-e", "until while 1; end; end"]) do |stdout, stderr, status|
assert_include(stdout.shift, "== disasm:")
assert_include(stdout.pop, "leave")
assert_predicate(status, :success?)
end
end
end end