From 386a729209418053faf3f385d9dfc519c4f5e960 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Dec 2012 17:07:58 +0900 Subject: [PATCH] Remove dead nodes from dags. Dead nodes are those that generate unused values (unassigned leaf nodes, expressions or destinationless move(p) nodes). The revoval is done by the flow analysis code (via the dags code) so that any pre and post removal flow analysis and manipulation may be done (eg, available expressions). --- tools/qfcc/include/dags.h | 3 +++ tools/qfcc/source/dags.c | 50 +++++++++++++++++++++++++++++++++++-- tools/qfcc/source/dot_dag.c | 3 +++ tools/qfcc/source/flow.c | 15 +++++++++++ 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index c3ff13502..21ac8c943 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -86,6 +86,8 @@ typedef struct dag_s { dagnode_t **nodes; ///< array of all dagnodes in this dag int num_nodes; int *topo; ///< nodes in topological sort order + int num_topo; ///< number of nodes in topo (may be < + ///< num_nodes after dead node removal) daglabel_t **labels; ///< array of all daglabels in this dag int num_labels;; struct set_s *roots; ///< set of root nodes @@ -105,6 +107,7 @@ void dot_dump_dag (void *_dag, const char *filename); */ dag_t *dag_create (struct flownode_s *flownode); +void dag_remove_dead_nodes (dag_t *dag); void dag_generate (dag_t *dag, sblock_t *block); //@} diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 3759720b5..b19a90aa1 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -551,12 +551,19 @@ dag_sort_nodes (dag_t *dag) set_iter_t *root_iter; set_t *visited = set_new (); int topo = 0; + int *tmp_topo; - dag->topo = malloc (dag->num_nodes * sizeof (int)); + if (dag->topo) + free (dag->topo); + dag->topo = alloca (dag->num_nodes * sizeof (int)); for (root_iter = set_first (dag->roots); root_iter; root_iter = set_next (root_iter)) dag_sort_visit (dag, visited, root_iter->element, &topo); set_delete (visited); + tmp_topo = malloc (topo * sizeof (int)); + memcpy (tmp_topo, dag->topo, topo * sizeof (int)); + dag->topo = tmp_topo; + dag->num_topo = topo; } static void @@ -893,11 +900,50 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) dagnode->value = dst; } +void +dag_remove_dead_nodes (dag_t *dag) +{ + int added_root; + set_iter_t *root_i, *child_i; + dagnode_t *node, *child; + + do { + added_root = 0; + for (root_i = set_first (dag->roots); root_i; + root_i = set_next (root_i)) { + node = dag->nodes[root_i->element]; + // only st_none (leaf nodes), st_expr and st_move can become + // dead nodes (no live vars attached). + if (node->type != st_none && node->type != st_expr + && node->type != st_move) + continue; + if (!set_is_empty (node->identifiers)) + continue; + // MOVEP with a variable destination pointer is never dead + if (node->type == st_move && node->children[3]) + continue; + set_remove (dag->roots, node->number); + for (child_i = set_first (node->edges); child_i; + child_i = set_next (child_i)) { + child = dag->nodes[child_i->element]; + if (!set_is_member (child->parents, node->number)) + continue; // not really a child (dependency edge) + set_remove (child->parents, node->number); + if (set_is_empty (child->parents)) { + set_add (dag->roots, child->number); + added_root = 1; + } + } + } + } while (added_root); + dag_sort_nodes (dag); +} + void dag_generate (dag_t *dag, sblock_t *block) { int i; - for (i = 0; i < dag->num_nodes; i++) + for (i = 0; i < dag->num_topo; i++) dag_gencode (dag, block, dag->nodes[dag->topo[i]]); } diff --git a/tools/qfcc/source/dot_dag.c b/tools/qfcc/source/dot_dag.c index 2c3f88386..bf0e26c63 100644 --- a/tools/qfcc/source/dot_dag.c +++ b/tools/qfcc/source/dot_dag.c @@ -105,6 +105,9 @@ print_node (dstring_t *dstr, dag_t *dag, dagnode_t *node) set_t *edges = set_new (); set_iter_t *edge_iter; + if (!set_is_member (dag->roots, node->number) + && set_is_empty (node->parents)) + return; set_assign (edges, node->edges); for (i = 0; i < 3; i++) { if (node->children[i]) { diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index f7c6fc9b0..9f2c74d60 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -714,6 +714,20 @@ flow_build_dags (flowgraph_t *graph) dump_dot ("dags", graph, dump_dot_flow_dags); } +static void +flow_cleanup_dags (flowgraph_t *graph) +{ + int i; + flownode_t *node; + + for (i = 0; i < graph->num_nodes; i++) { + node = graph->nodes[i]; + dag_remove_dead_nodes (node->dag); + } + if (options.block_dot.dags) + dump_dot ("cleaned-dags", graph, dump_dot_flow_dags); +} + static sblock_t * flow_generate (flowgraph_t *graph) { @@ -1253,5 +1267,6 @@ flow_data_flow (function_t *func) dump_dot ("live", graph, dump_dot_flow_live); flow_uninitialized (graph); flow_build_dags (graph); + flow_cleanup_dags (graph); func->sblock = flow_generate (graph); }