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

View File

@ -871,4 +871,12 @@ class TestISeq < Test::Unit::TestCase
RubyVM::InstructionSequence.load_from_binary(var_0)
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