Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}