зеркало из 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>
|
Sun Nov 22 16:37:10 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* compile.c (iseq_peephole_optimize): eliminate always/never
|
* compile.c (iseq_peephole_optimize): eliminate always/never
|
||||||
|
|
44
compile.c
44
compile.c
|
@ -1905,6 +1905,30 @@ replace_destination(INSN *dobj, INSN *nobj)
|
||||||
if (!dl->refcnt) REMOVE_ELEM(&dl->link);
|
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
|
static int
|
||||||
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
|
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
|
||||||
{
|
{
|
||||||
|
@ -1935,11 +1959,11 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
|
||||||
unref_destination(iobj);
|
unref_destination(iobj);
|
||||||
REMOVE_ELEM(&iobj->link);
|
REMOVE_ELEM(&iobj->link);
|
||||||
}
|
}
|
||||||
else if (iobj != diobj && diobj->insn_id == BIN(jump)) {
|
else if (iobj != diobj && diobj->insn_id == BIN(jump) &&
|
||||||
if (OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
|
OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
|
||||||
replace_destination(iobj, diobj);
|
replace_destination(iobj, diobj);
|
||||||
goto again;
|
remove_unreachable_chunk(iobj->link.next);
|
||||||
}
|
goto again;
|
||||||
}
|
}
|
||||||
else if (diobj->insn_id == BIN(leave)) {
|
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);
|
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) ||
|
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 *redo_label = iseq->compile_data->redo_label = NEW_LABEL(line); /* redo */
|
||||||
LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(line); /* break */
|
LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(line); /* break */
|
||||||
LABEL *end_label = NEW_LABEL(line);
|
LABEL *end_label = NEW_LABEL(line);
|
||||||
|
LABEL *adjust_label = NEW_LABEL(line);
|
||||||
|
|
||||||
LABEL *next_catch_label = NEW_LABEL(line);
|
LABEL *next_catch_label = NEW_LABEL(line);
|
||||||
LABEL *tmp_label = NULL;
|
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);
|
tmp_label = NEW_LABEL(line);
|
||||||
ADD_INSNL(ret, line, jump, tmp_label);
|
ADD_INSNL(ret, line, jump, tmp_label);
|
||||||
}
|
}
|
||||||
|
ADD_LABEL(ret, adjust_label);
|
||||||
ADD_INSN(ret, line, putnil);
|
ADD_INSN(ret, line, putnil);
|
||||||
ADD_LABEL(ret, next_catch_label);
|
ADD_LABEL(ret, next_catch_label);
|
||||||
ADD_INSN(ret, line, pop);
|
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_LABEL(ret, end_label);
|
||||||
|
ADD_ADJUST_RESTORE(ret, adjust_label);
|
||||||
|
|
||||||
if (node->nd_state == Qundef) {
|
if (node->nd_state == Qundef) {
|
||||||
/* ADD_INSN(ret, line, putundef); */
|
/* 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;
|
if (!cc) return right;
|
||||||
cc = cond0(parser, cc);
|
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);
|
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)
|
logop_gen(struct parser_params *parser, enum node_type type, NODE *left, NODE *right)
|
||||||
{
|
{
|
||||||
value_expr(left);
|
value_expr(left);
|
||||||
if (!left) {
|
if (left && (enum node_type)nd_type(left) == type) {
|
||||||
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) {
|
|
||||||
NODE *node = left, *second;
|
NODE *node = left, *second;
|
||||||
while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
|
while ((second = node->nd_2nd) != 0 && (enum node_type)nd_type(second) == type) {
|
||||||
node = second;
|
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);
|
node->nd_2nd = NEW_NODE(type, second, right, 0);
|
||||||
return left;
|
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);
|
return NEW_NODE(type, left, right, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -633,6 +633,18 @@ eom
|
||||||
assert_valid_syntax("a\n&.foo")
|
assert_valid_syntax("a\n&.foo")
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def not_label(x) @result = x; @not_label ||= nil end
|
def not_label(x) @result = x; @not_label ||= nil end
|
||||||
|
|
Загрузка…
Ссылка в новой задаче