From: nobu.nokada@... Date: 2004-02-02T22:08:48+09:00 Subject: peephole optimization (Re: Bignums and return) Hi, At Sun, 1 Feb 2004 01:04:52 +0900, Mark J. Reed wrote: > Anyway, the point is that any extra code inserted by the "return" > should be optimized out when the return doesn't do anything. Not yet. * parse.y (remove_return): remove tail returns. [ruby-talk:90934] Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.314 diff -u -2 -p -r1.314 parse.y --- parse.y 2 Feb 2004 13:06:35 -0000 1.314 +++ parse.y 2 Feb 2004 13:07:19 -0000 @@ -120,4 +120,5 @@ static NODE *remove_begin(); #define value_expr(node) value_expr0((node) = remove_begin(node)) #define void_expr(node) void_expr0((node) = remove_begin(node)) +static void reduce_nodes(); static NODE *block_append(); @@ -365,5 +366,10 @@ bodystmt : compstmt } if ($4) { - $$ = NEW_ENSURE($$, $4); + if ($$) { + $$ = NEW_ENSURE($$, $4); + } + else { + $$ = block_append($4, NEW_NIL()); + } } fixpos($$, $1); @@ -1650,5 +1656,7 @@ primary : literal kEND { - $$ = NEW_DEFN($2, $4, $5, NOEX_PRIVATE); + NODE *body = remove_begin($5); + reduce_nodes(&body); + $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE); fixpos($$, $4); local_pop(); @@ -1666,5 +1674,7 @@ primary : literal kEND { - $$ = NEW_DEFS($2, $5, $7, $8); + NODE *body = remove_begin($8); + reduce_nodes(&body); + $$ = NEW_DEFS($2, $5, $7, body); fixpos($$, $2); local_pop(); @@ -4498,5 +4513,5 @@ block_append(head, tail) NODE *head, *tail; { - NODE *end, *h = head; + NODE *end, *h = head, *nd; if (tail == 0) return head; @@ -4519,18 +4534,18 @@ block_append(head, tail) } - if (RTEST(ruby_verbose)) { - NODE *nd = end->nd_head; - switch (nd_type(nd)) { - case NODE_RETURN: - case NODE_BREAK: - case NODE_NEXT: - case NODE_REDO: - case NODE_RETRY: + nd = end->nd_head; + switch (nd_type(nd)) { + case NODE_RETURN: + case NODE_BREAK: + case NODE_NEXT: + case NODE_REDO: + case NODE_RETRY: + if (RTEST(ruby_verbose)) { parser_warning(nd, "statement not reached"); - break; - - default: - break; } + break; + + default: + break; } @@ -5103,4 +5118,54 @@ remove_begin(node) } return node; +} + +static void +reduce_nodes(body) + NODE **body; +{ + NODE *node = *body; + +#define subnodes(n1, n2) \ + ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \ + (!node->n2) ? (body = &node->n1, 1) : \ + (reduce_nodes(&node->n1), body = &node->n2, 1)) + + while (node) { + switch (nd_type(node)) { + end: + case NODE_NIL: + *body = 0; + return; + case NODE_RETURN: + *body = node = node->nd_stts; + continue; + case NODE_BEGIN: + *body = node = node->nd_body; + continue; + case NODE_BLOCK: + body = &node->nd_end->nd_head; + break; + case NODE_IF: + if (subnodes(nd_body, nd_else)) break; + return; + case NODE_CASE: + body = &node->nd_body; + break; + case NODE_WHEN: + if (!subnodes(nd_body, nd_next)) goto end; + break; + case NODE_ENSURE: + if (!subnodes(nd_head, nd_resq)) goto end; + break; + case NODE_RESCUE: + if (!subnodes(nd_head, nd_resq)) goto end; + break; + default: + return; + } + node = *body; + } + +#undef subnodes } -- Nobu Nakada