Skip to content

Commit 12abe9e

Browse files
byrootjhawthorn
andcommitted
compile.c: statically resolve swap instructions when possible
If the two preceeding instructions are known not to be dependent on the state of the stack, then we can eliminate the `swap` and inverse the two previous instructions. Co-Authored-By: John Hawthorn <john@hawthorn.email>
1 parent 14a257c commit 12abe9e

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

compile.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
364384
RBIMPL_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+
12281267
static LINK_ELEMENT *
12291268
FIRST_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

Comments
 (0)