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).
This commit is contained in:
Bill Currie 2012-12-25 17:07:58 +09:00
parent 3baa73e60e
commit 386a729209
4 changed files with 69 additions and 2 deletions

View file

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

View file

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

View file

@ -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]) {

View file

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