Calculate reaching defs.

This commit is contained in:
Bill Currie 2012-12-09 22:37:59 +09:00
parent 6473951daa
commit e4dd86c36b
3 changed files with 115 additions and 3 deletions

View file

@ -70,6 +70,12 @@ typedef struct flownode_s {
struct set_s *edges; ///< edges leaving this node to successor nodes
struct set_s *dom; ///< dominating nodes
struct set_s *global_vars; ///< global vars used by function
struct {
struct set_s *gen;
struct set_s *kill;
struct set_s *in;
struct set_s *out;
} reaching_defs;
struct {
struct set_s *use;
struct set_s *def;
@ -109,6 +115,7 @@ void flow_data_flow (struct function_s *func);
void dump_dot_flow (void *g, const char *filename);
void dump_dot_flow_dags (void *g, const char *filename);
void dump_dot_flow_live (void *g, const char *filename);
void dump_dot_flow_reaching (void *g, const char *filename);
//@}

View file

@ -200,10 +200,35 @@ print_flow_node_live (dstring_t *dstr, flowgraph_t *graph, flownode_t *node,
}
}
static void
print_flow_node_reaching (dstring_t *dstr, flowgraph_t *graph,
flownode_t *node, int level)
{
int indent = level * 2 + 2;
int reach;
set_t *gen = node->reaching_defs.gen;
set_t *kill = node->reaching_defs.kill;
set_t *in = node->reaching_defs.in;
set_t *out = node->reaching_defs.out;
reach = gen && kill && in && out;
if (reach) {
dasprintf (dstr, "%*sfn_%p [label=\"", indent, "", node);
dasprintf (dstr, "gen: %s\\n", set_as_string (gen));
dasprintf (dstr, "kill: %s\\n", set_as_string (kill));
dasprintf (dstr, "in: %s\\n", set_as_string (in));
dasprintf (dstr, "out: %s\"];\n", set_as_string (out));
} else {
print_flow_node (dstr, graph, node, level);
}
}
static flow_dot_t flow_dot_methods[] = {
{"", print_flow_node, print_flow_edge},
{"dag", print_flow_node_dag, print_flow_edge_dag},
{"live", print_flow_node_live, print_flow_edge},
{"", print_flow_node, print_flow_edge},
{"dag", print_flow_node_dag, print_flow_edge_dag},
{"live", print_flow_node_live, print_flow_edge},
{"reaching",print_flow_node_reaching, print_flow_edge},
};
static void
@ -254,3 +279,9 @@ dump_dot_flow_live (void *g, const char *filename)
{
print_flowgraph (&flow_dot_methods[2], (flowgraph_t *) g, filename);
}
void
dump_dot_flow_reaching (void *g, const char *filename)
{
print_flowgraph (&flow_dot_methods[3], (flowgraph_t *) g, filename);
}

View file

@ -373,6 +373,78 @@ flow_build_vars (function_t *func)
set_delete (stdef);
}
static void
flow_reaching_defs (flowgraph_t *graph)
{
int i;
int changed;
flownode_t *node;
statement_t *st;
set_t *stdef = set_new ();
set_t *stgen = set_new ();
set_t *stkill = set_new ();
set_t *oldout = set_new ();
set_t *gen, *kill, *in, *out;
set_iter_t *var_i;
set_iter_t *pred_i;
flowvar_t *var;
// First, calculate gen and kill for each block, and initialize in and out
for (i = 0; i < graph->num_nodes; i++) {
node = graph->nodes[i];
gen = set_new ();
kill = set_new ();
for (st = node->sblock->statements; st; st = st->next) {
flow_analyze_statement (st, 0, stdef, 0, 0);
set_empty (stgen);
set_empty (stkill);
for (var_i = set_first (stdef); var_i; var_i = set_next (var_i)) {
var = graph->func->vars[var_i->value];
set_union (stkill, var->define);
set_remove (stkill, st->number);
set_add (stgen, st->number);
}
set_difference (gen, stkill);
set_union (gen, stgen);
set_difference (kill, stgen);
set_union (kill, stkill);
}
node->reaching_defs.gen = gen;
node->reaching_defs.kill = kill;
node->reaching_defs.in = set_new ();
node->reaching_defs.out = set_new ();
}
while (changed) {
changed = 0;
// flow down the graph
for (i = 0; i < graph->num_nodes; i++) {
node = graph->nodes[graph->dfo[i]];
in = node->reaching_defs.in;
out = node->reaching_defs.out;
gen = node->reaching_defs.gen;
kill = node->reaching_defs.kill;
for (pred_i = set_first (node->predecessors); pred_i;
pred_i = set_next (pred_i)) {
flownode_t *pred = graph->nodes[pred_i->value];
set_union (in, pred->reaching_defs.out);
}
set_assign (oldout, out);
set_assign (out, in);
set_difference (out, kill);
set_union (out, gen);
if (!set_is_equivalent (out, oldout))
changed = 1;
}
}
set_delete (oldout);
set_delete (stdef);
set_delete (stgen);
set_delete (stkill);
}
static void
live_set_use (set_t *stuse, set_t *use, set_t *def)
{
@ -988,6 +1060,8 @@ flow_data_flow (function_t *func)
flow_build_vars (func);
graph = flow_build_graph (func);
func->graph = graph;
flow_reaching_defs (graph);
dump_dot ("reaching", graph, dump_dot_flow_reaching);
flow_live_vars (graph);
flow_uninitialized (graph);
flow_build_dags (graph);