зеркало из https://github.com/github/ruby.git
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
This commit is contained in:
Родитель
792c822ec4
Коммит
7dc4929214
|
@ -1,3 +1,11 @@
|
|||
Sun Nov 22 16:53:34 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* 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.
|
||||
|
||||
Sun Nov 22 16:37:10 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* compile.c (iseq_peephole_optimize): eliminate always/never
|
||||
|
|
40
compile.c
40
compile.c
|
@ -1905,6 +1905,30 @@ replace_destination(INSN *dobj, INSN *nobj)
|
|||
if (!dl->refcnt) REMOVE_ELEM(&dl->link);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1935,12 +1959,12 @@ 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)) {
|
||||
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)) {
|
||||
/*
|
||||
* jump LABEL
|
||||
|
@ -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); */
|
||||
|
|
29
parse.y
29
parse.y
|
@ -9747,15 +9747,6 @@ new_if_gen(struct parser_params *parser, NODE *cc, NODE *left, NODE *right)
|
|||
{
|
||||
if (!cc) return right;
|
||||
cc = cond0(parser, cc);
|
||||
switch (nd_type(cc)) {
|
||||
case NODE_NIL:
|
||||
case NODE_FALSE:
|
||||
return right;
|
||||
case NODE_TRUE:
|
||||
case NODE_LIT:
|
||||
case NODE_STR:
|
||||
return left;
|
||||
}
|
||||
return NEW_IF(cc, left, right);
|
||||
}
|
||||
|
||||
|
@ -9763,11 +9754,7 @@ static NODE*
|
|||
logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *right)
|
||||
{
|
||||
value_expr(left);
|
||||
if (!left) {
|
||||
if (!in_defined && type == NODE_AND) return 0;
|
||||
/* make NODE_OR not to be "void value expression" */
|
||||
}
|
||||
else if ((enum node_type)nd_type(left) == type) {
|
||||
if (left && (enum node_type)nd_type(left) == type) {
|
||||
NODE *node = left, *second;
|
||||
while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
|
||||
node = second;
|
||||
|
@ -9775,20 +9762,6 @@ logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *r
|
|||
node->nd_2nd = NEW_NODE(type, second, right, 0);
|
||||
return left;
|
||||
}
|
||||
else if (!in_defined) {
|
||||
switch (nd_type(left)) {
|
||||
case NODE_NIL:
|
||||
case NODE_FALSE:
|
||||
if (type == NODE_AND) return left;
|
||||
break;
|
||||
case NODE_TRUE:
|
||||
case NODE_LIT:
|
||||
case NODE_STR:
|
||||
if (type != NODE_AND) return left;
|
||||
nd_set_type(left, NODE_TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NEW_NODE(type, left, right, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -633,6 +633,18 @@ eom
|
|||
assert_valid_syntax("a\n&.foo")
|
||||
end
|
||||
|
||||
def test_no_warning_logop_literal
|
||||
assert_warning("") do
|
||||
eval("true||raise;nil")
|
||||
end
|
||||
assert_warning("") do
|
||||
eval("false&&raise;nil")
|
||||
end
|
||||
assert_warning("") do
|
||||
eval("''||raise;nil")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def not_label(x) @result = x; @not_label ||= nil end
|
||||
|
|
Загрузка…
Ссылка в новой задаче