@@ -359,6 +359,26 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NOD
359359#define IS_NEXT_INSN_ID(link, insn) \
360360 ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn))
361361
362+ static inline bool
363+ IS_INDEPENDENT_INSN(LINK_ELEMENT *link)
364+ {
365+ if (!IS_INSN(link)) {
366+ return false;
367+ }
368+
369+ enum ruby_vminsn_type type = INSN_OF(link);
370+
371+ return (
372+ type == BIN(putobject) ||
373+ type == BIN(putspecialobject) ||
374+ type == BIN(putnil) ||
375+ type == BIN(putself) ||
376+ type == BIN(duphash) ||
377+ type == BIN(getinstancevariable) ||
378+ type == BIN(getlocal)
379+ );
380+ }
381+
362382/* error */
363383#if CPDEBUG > 0
364384RBIMPL_ATTR_NORETURN()
@@ -1225,6 +1245,25 @@ ELEM_REMOVE(LINK_ELEMENT *elem)
12251245 }
12261246}
12271247
1248+ /*
1249+ * elem1, elem2 => elem2, elem1
1250+ */
1251+ static void
1252+ ELEM_SWAP(LINK_ELEMENT *first, LINK_ELEMENT *second)
1253+ {
1254+ RUBY_ASSERT(first->next == second);
1255+ RUBY_ASSERT(first == second->prev);
1256+
1257+ first->prev->next = second;
1258+ second->next->prev = first;
1259+
1260+ first->next = second->next;
1261+ second->next = first;
1262+
1263+ second->prev = first->prev;
1264+ first->prev = second;
1265+ }
1266+
12281267static LINK_ELEMENT *
12291268FIRST_ELEMENT(const LINK_ANCHOR *const anchor)
12301269{
@@ -4253,6 +4292,24 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
42534292 }
42544293 }
42554294
4295+ if (iobj->link.next && iobj->link.next->next && IS_NEXT_INSN_ID(iobj->link.next, swap)) {
4296+ LINK_ELEMENT *first = &iobj->link;
4297+ LINK_ELEMENT *second = first->next;
4298+ LINK_ELEMENT *swap = second->next;
4299+ /*
4300+ * putself / (or any other independent instruction)
4301+ * putnil / (or any other independent instruction)
4302+ * swap
4303+ * =>
4304+ * putnil / (or any other independent instruction)
4305+ * putself / (or any other independent instruction)
4306+ */
4307+ if (IS_INSN_ID(swap, swap) && IS_INDEPENDENT_INSN(first) && IS_INDEPENDENT_INSN(second)) {
4308+ ELEM_REMOVE(swap);
4309+ ELEM_SWAP(first, second);
4310+ }
4311+ }
4312+
42564313 return COMPILE_OK;
42574314}
42584315
0 commit comments