static void flow_find_dominators (flowgraph_t *graph) { set_t *work; flownode_t *node; int i; set_iter_t *pred; int changed; if (!graph->num_nodes) return; // First, create a base set for the initial state of the non-initial nodes work = set_new (); for (i = 0; i < graph->num_nodes; i++) set_add (work, i); set_add (graph->nodes[0]->dom, 0); // initialize dom for the non-initial nodes for (i = 1; i < graph->num_nodes; i++) { set_assign (graph->nodes[i]->dom, work); } do { changed = 0; for (i = 1; i < graph->num_nodes; i++) { node = graph->nodes[i]; pred = set_first (node->predecessors); set_empty (work); for (pred = set_first (node->predecessors); pred; pred = set_next (pred)) set_intersection (work, graph->nodes[pred->element]->dom); set_add (work, i); if (!set_is_equivalent (work, node->dom)) changed = 1; set_assign (node->dom, work); } } while (changed); set_delete (work); }
static void flow_uninitialized (flowgraph_t *graph) { int i; flownode_t *node; flowvar_t *var; set_iter_t *var_i; set_t *defs; set_t *uninitialized; uninitialized = set_new (); node = graph->nodes[graph->num_nodes]; set_assign (uninitialized, node->reaching_defs.out); defs = set_new (); for (i = 0; i < graph->num_nodes; i++) { node = graph->nodes[graph->dfo[i]]; set_empty (defs); // collect definitions of all variables "used" in this node. use from // the live vars analysis is perfect for the job for (var_i = set_first (node->live_vars.use); var_i; var_i = set_next (var_i)) { var = graph->func->vars[var_i->element]; set_union (defs, var->define); } // interested in only those defintions that actually reach this node set_intersection (defs, node->reaching_defs.in); // if any of the definitions come from the entry dummy block, then // the statements need to be scanned in case an aliasing definition // kills the dummy definition before the usage, and also so the line // number information can be obtained from the statement. if (set_is_intersecting (defs, uninitialized)) flow_uninit_scan_statements (node, defs, uninitialized); } set_delete (defs); }
void _type_copy_set(const void* cpv_first, const void* cpv_second, void* pv_output) { assert(cpv_first != NULL && cpv_second != NULL && pv_output != NULL); set_assign((set_t*)cpv_first, (set_t*)cpv_second); *(bool_t*)pv_output = true; }
static void flow_live_vars (flowgraph_t *graph) { int i, j; flownode_t *node; set_t *use; set_t *def; set_t *stuse = set_new (); set_t *stdef = set_new (); set_t *tmp = set_new (); set_iter_t *succ; statement_t *st; int changed = 1; // first, calculate use and def for each block, and initialize the in and // out sets. for (i = 0; i < graph->num_nodes; i++) { node = graph->nodes[i]; use = set_new (); def = set_new (); for (st = node->sblock->statements; st; st = st->next) { flow_analyze_statement (st, stuse, stdef, 0, 0); live_set_use (stuse, use, def); live_set_def (stdef, use, def); } node->live_vars.use = use; node->live_vars.def = def; node->live_vars.in = set_new (); node->live_vars.out = set_new (); } // create in for the exit dummy block using the global vars used by the // function use = set_new (); set_assign (use, graph->func->global_vars); node = graph->nodes[graph->num_nodes + 1]; node->live_vars.in = use; node->live_vars.out = set_new (); node->live_vars.use = set_new (); node->live_vars.def = set_new (); while (changed) { changed = 0; // flow UP the graph because live variable analysis uses information // from a node's successors rather than its predecessors. for (j = graph->num_nodes - 1; j >= 0; j--) { node = graph->nodes[graph->dfo[j]]; set_empty (tmp); for (succ = set_first (node->successors); succ; succ = set_next (succ)) set_union (tmp, graph->nodes[succ->element]->live_vars.in); if (!set_is_equivalent (node->live_vars.out, tmp)) { changed = 1; set_assign (node->live_vars.out, tmp); } set_assign (node->live_vars.in, node->live_vars.out); set_difference (node->live_vars.in, node->live_vars.def); set_union (node->live_vars.in, node->live_vars.use); } } set_delete (stuse); set_delete (stdef); set_delete (tmp); }
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, *uninit; set_iter_t *var_i; set_iter_t *pred_i; flowvar_t *var; // First, create out for the entry dummy node using fake statement numbers. kill = set_new (); for (i = 0; i < graph->func->num_statements; i++) set_add (kill, i); uninit = set_new (); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; set_union (uninit, var->define);// do not want alias handling here set_difference (uninit, kill); // remove any gens from the function } graph->nodes[graph->num_nodes]->reaching_defs.out = uninit; graph->nodes[graph->num_nodes]->reaching_defs.in = set_new (); graph->nodes[graph->num_nodes]->reaching_defs.gen = set_new (); graph->nodes[graph->num_nodes]->reaching_defs.kill = set_new (); // 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->element]; flow_kill_aliases (stkill, var, uninit); 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 (); } changed = 1; 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->element]; 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); }