mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Calculate reaching defs.
This commit is contained in:
parent
6473951daa
commit
e4dd86c36b
3 changed files with 115 additions and 3 deletions
|
@ -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);
|
||||
|
||||
//@}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue