summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-06-16 16:52:44 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-06-16 16:59:12 -0400
commit15e96a558baf007966f80d565f50f18cd2ecd75d (patch)
tree5211eac20723cc6969f41b5e6617cc58698d29ce
parentc684ba9a5564edf5c43ce9bcae56b9b84df340c3 (diff)
Optimize away stores to variables that are never read
-rw-r--r--optimize.c85
1 files changed, 76 insertions, 9 deletions
diff --git a/optimize.c b/optimize.c
index ccb11d7..508f5e6 100644
--- a/optimize.c
+++ b/optimize.c
@@ -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;
}