diff --git a/ChangeLog b/ChangeLog index b5a13556d9..2075e954e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Nov 18 11:32:15 2015 Nobuyoshi Nakada + + * compile.c (iseq_peephole_optimize): eliminate always/never + branches after a literal object. this sequence typically + appears by defined? operator for a method call on a local + variable. + Wed Nov 18 10:33:06 2015 NAKAMURA Usaku * ext/socket/ancdata.c (bsock_recvmsg_internal): stretch the buffer size diff --git a/compile.c b/compile.c index f66f12e94b..ae900fbf31 100644 --- a/compile.c +++ b/compile.c @@ -2031,6 +2031,33 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal */ replace_destination(iobj, nobj); } + else if (pobj) { + int cond; + if (pobj->insn_id == BIN(putobject)) { + cond = (iobj->insn_id == BIN(branchif) ? + OPERAND_AT(pobj, 0) != Qfalse : + iobj->insn_id == BIN(branchunless) ? + OPERAND_AT(pobj, 0) == Qfalse : + FALSE); + } + else if (pobj->insn_id == BIN(putstring)) { + cond = iobj->insn_id == BIN(branchif); + } + else if (pobj->insn_id == BIN(putnil)) { + cond = iobj->insn_id != BIN(branchif); + } + else break; + REMOVE_ELEM(&pobj->link); + if (cond) { + iobj->insn_id = BIN(jump); + goto again; + } + else { + unref_destination(iobj); + REMOVE_ELEM(&iobj->link); + } + break; + } else break; nobj = (INSN *)get_destination_insn(nobj); }