mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
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:
parent
3baa73e60e
commit
386a729209
4 changed files with 69 additions and 2 deletions
|
@ -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);
|
||||
|
||||
//@}
|
||||
|
|
|
@ -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]]);
|
||||
}
|
||||
|
|
|
@ -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]) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue