summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-22 07:53:37 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-22 07:53:37 +0000
commit7dc4929214e608f52774cd026ea8cc173e49e6d1 (patch)
treefc323ff2449a0139c6f97472dba30e3870cc4503 /compile.c
parent792c822ec441a9a061a2c74ddd970005fab33ab6 (diff)
downloadruby-7dc4929214e608f52774cd026ea8cc173e49e6d1.tar.gz
compile.c: move logop DCE
* compile.c (iseq_peephole_optimize): remove unreachable code chunk after jump/leave. * parse.y: move dead code elimination of logical operation to compile.c. not to warn logical operation of literal constants. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52711 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/compile.c b/compile.c
index 54cf643f48..771361dd56 100644
--- a/compile.c
+++ b/compile.c
@@ -1906,6 +1906,30 @@ replace_destination(INSN *dobj, INSN *nobj)
}
static int
+remove_unreachable_chunk(LINK_ELEMENT *i)
+{
+ int removed = 0;
+ while (i) {
+ if (i->type == ISEQ_ELEMENT_INSN) {
+ switch (INSN_OF(i)) {
+ case BIN(jump):
+ case BIN(branchif):
+ case BIN(branchunless):
+ case BIN(branchnil):
+ unref_destination((INSN *)i);
+ default:
+ break;
+ }
+ }
+ else break;
+ REMOVE_ELEM(i);
+ removed = 1;
+ i = i->next;
+ }
+ return removed;
+}
+
+static int
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
{
INSN *iobj = (INSN *)list;
@@ -1935,11 +1959,11 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
unref_destination(iobj);
REMOVE_ELEM(&iobj->link);
}
- else if (iobj != diobj && diobj->insn_id == BIN(jump)) {
- if (OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
- replace_destination(iobj, diobj);
- goto again;
- }
+ else if (iobj != diobj && diobj->insn_id == BIN(jump) &&
+ OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
+ replace_destination(iobj, diobj);
+ remove_unreachable_chunk(iobj->link.next);
+ goto again;
}
else if (diobj->insn_id == BIN(leave)) {
/*
@@ -1988,6 +2012,13 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
REMOVE_ELEM(&iobj->link);
}
}
+ else if (remove_unreachable_chunk(iobj->link.next)) {
+ goto again;
+ }
+ }
+
+ if (iobj->insn_id == BIN(leave)) {
+ remove_unreachable_chunk(iobj->link.next);
}
if (iobj->insn_id == BIN(branchif) ||
@@ -3788,6 +3819,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
LABEL *redo_label = iseq->compile_data->redo_label = NEW_LABEL(line); /* redo */
LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(line); /* break */
LABEL *end_label = NEW_LABEL(line);
+ LABEL *adjust_label = NEW_LABEL(line);
LABEL *next_catch_label = NEW_LABEL(line);
LABEL *tmp_label = NULL;
@@ -3802,6 +3834,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
tmp_label = NEW_LABEL(line);
ADD_INSNL(ret, line, jump, tmp_label);
}
+ ADD_LABEL(ret, adjust_label);
ADD_INSN(ret, line, putnil);
ADD_LABEL(ret, next_catch_label);
ADD_INSN(ret, line, pop);
@@ -3829,6 +3862,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
ADD_LABEL(ret, end_label);
+ ADD_ADJUST_RESTORE(ret, adjust_label);
if (node->nd_state == Qundef) {
/* ADD_INSN(ret, line, putundef); */