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); }