diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-06-16 16:52:44 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-06-16 16:59:12 -0400 |
commit | 15e96a558baf007966f80d565f50f18cd2ecd75d (patch) | |
tree | 5211eac20723cc6969f41b5e6617cc58698d29ce | |
parent | c684ba9a5564edf5c43ce9bcae56b9b84df340c3 (diff) |
Optimize away stores to variables that are never read
-rw-r--r-- | optimize.c | 85 |
1 files changed, 76 insertions, 9 deletions
@@ -402,21 +402,35 @@ peephole (node_t *node, *changed = TRUE; } + else if (node_is (node0, NODE_STORE) && + !node0->store.definition->used) + { + node0->common.type = NODE_POP; + + *changed = TRUE; + } + else if (node_is (node0, NODE_STORE_IND) && + !node0->store_ind.definition->used) + { + node0->common.type = NODE_POP; + + *changed = TRUE; + } node->common.next = peephole (node->common.next, changed); return node; } -gboolean -optimize (ast_t *ast) +static void +do_optimize (ast_t *ast, gboolean *changed) { GList *list; node_t **node = NULL; node_t **entry = NULL; for (list = ast->common.children->head; list != NULL; list = list->next) - optimize (list->data); + do_optimize (list->data, changed); if (ast_is (ast, AST_PROGRAM, 0)) { @@ -430,22 +444,75 @@ optimize (ast_t *ast) entry = &(function->enter); } - + if (entry) { - gboolean changed; + gboolean c; node = entry; do { - changed = FALSE; + c = FALSE; + + *node = peephole (*node, &c); + *node = remove_nops (*node, &c); - *node = peephole (*node, &changed); - *node = remove_nops (*node, &changed); + if (c) + *changed = TRUE; } - while (changed); + while (c); } +} + +static void +mark_variables_unused (ast_t *ast) +{ + GList *list; + + for (list = ast->common.children->head; list != NULL; list = list->next) + mark_variables_unused (list->data); + + if (ast_is (ast, AST_DEFINITION, AST_VARIABLE_DEFINITION)) + { + ast_variable_definition_t *variable = &ast->definition.variable; + + variable->used = FALSE; + } +} + +static void +mark_used (node_t *node, gpointer data) +{ + if (node->common.type == NODE_LOAD) + { + node->load.definition->used = TRUE; + } + else if (node->common.type == NODE_LOAD_IND) + { + node->load_ind.definition->used = TRUE; + } +} + +gboolean +optimize (ast_t *ast) +{ + gboolean changed; + + do + { + changed = FALSE; + + mark_variables_unused (ast); + node_breadth_first (ast->program.enter, mark_used, NULL); + + do_optimize (ast, &changed); + } while (changed); + /* The offsets pass also uses the "used" field in + * ast_variable_definition_t, and it expects it + * to start out as FALSE, so clear it here. + */ + mark_variables_unused (ast); return TRUE; } |