From bb3f2ce7523b42f70243025a437583fc4d64a528 Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 21 Oct 2017 23:30:39 +0000 Subject: [PATCH] compile.c: optimize local variable assignments * compile.c (iseq_peephole_optimize): eliminate repeated assignments and copy from/to a same local variable. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60322 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- compile.c | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/compile.c b/compile.c index 48d36c65ff..da75cfec5a 100644 --- a/compile.c +++ b/compile.c @@ -363,6 +363,8 @@ struct iseq_compile_data_ensure_node_stack { #define IS_LABEL(link) ((link)->type == ISEQ_ELEMENT_LABEL) #define IS_ADJUST(link) ((link)->type == ISEQ_ELEMENT_ADJUST) #define IS_INSN_ID(iobj, insn) (INSN_OF(iobj) == BIN(insn)) +#define IS_NEXT_INSN_ID(link, insn) \ + ((link)->next && IS_INSN((link)->next) && IS_INSN_ID((link)->next, insn)) /* error */ #if CPDEBUG > 0 @@ -2213,7 +2215,7 @@ iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj) static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt) { - INSN *iobj = (INSN *)list; + INSN *const iobj = (INSN *)list; again: if (IS_INSN_ID(iobj, jump)) { INSN *niobj, *diobj, *piobj; @@ -2571,6 +2573,40 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } + if (IS_INSN_ID(iobj, dup)) { + if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) { + LINK_ELEMENT *set1 = iobj->link.next, *set2 = NULL; + if (IS_NEXT_INSN_ID(set1, setlocal)) { + set2 = set1->next; + if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) && + OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) { + REMOVE_ELEM(set1); + REMOVE_ELEM(&iobj->link); + } + } + else if (IS_NEXT_INSN_ID(set1, dup) && + IS_NEXT_INSN_ID(set1->next, setlocal)) { + set2 = set1->next->next; + if (OPERAND_AT(set1, 0) == OPERAND_AT(set2, 0) && + OPERAND_AT(set1, 1) == OPERAND_AT(set2, 1)) { + REMOVE_ELEM(set1->next); + REMOVE_ELEM(set2); + } + } + } + } + + if (IS_INSN_ID(iobj, getlocal)) { + if (IS_NEXT_INSN_ID(&iobj->link, setlocal)) { + LINK_ELEMENT *set1 = iobj->link.next; + if (OPERAND_AT(iobj, 0) == OPERAND_AT(set1, 0) && + OPERAND_AT(iobj, 1) == OPERAND_AT(set1, 1)) { + REMOVE_ELEM(set1); + REMOVE_ELEM(&iobj->link); + } + } + } + #define IS_TRACE_LINE(insn) \ (IS_INSN_ID(insn, trace) && \ OPERAND_AT(insn, 0) == INT2FIX(RUBY_EVENT_LINE)) @@ -5132,18 +5168,19 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp case NODE_DASGN: case NODE_DASGN_CURR:{ int idx, lv, ls; + ID id = node->nd_vid; CHECK(COMPILE(ret, "dvalue", node->nd_value)); - debugi("dassn id", rb_id2str(node->nd_vid) ? node->nd_vid : '*'); + debugi("dassn id", rb_id2str(id) ? id : '*'); if (!popped) { ADD_INSN(ret, line, dup); } - idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); + idx = get_dyna_var_idx(iseq, id, &lv, &ls); if (idx < 0) { COMPILE_ERROR(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")", - rb_id2str(node->nd_vid)); + rb_id2str(id)); goto ng; } ADD_SETLOCAL(ret, line, ls - idx, lv);