Esempio n. 1
0
	/* Add local dominance frontiers */
	foreach_block_succ(blk, edge) {
		ir_node *y = get_edge_src_irn(edge);

		if (get_idom(y) != blk) {
			ARR_APP1(ir_node *, df_list, y);
		}
	}
Esempio n. 2
0
/**
 * implementation of create_set_func which produces a cond with control
 * flow
 */
static ir_node *create_cond_set(ir_node *cond_value, ir_mode *dest_mode)
{
	ir_node *lower_block = part_block_edges(cond_value);
	ir_node *upper_block = get_nodes_block(cond_value);
	foreach_out_edge_safe(upper_block, edge) {
		/* The cached nodes might belong to the lower block, so we have
		 * to clear the cache for moved nodes to avoid dominance problems. */
		ir_node *node = get_edge_src_irn(edge);
		set_irn_link(node, NULL);
	}
Esempio n. 3
0
/**
 * Check if a given value is last used (i.e. die after) the block of some
 * other node.
 */
static bool value_last_used_here(be_lv_t *lv, ir_node *here, ir_node *value)
{
	ir_node *block = get_nodes_block(here);

	/* If the value is live end it is for sure it does not die here */
	if (be_is_live_end(lv, block, value))
		return false;

	/* if multiple nodes in this block use the value, then we cannot decide
	 * whether the value will die here (because there is no schedule yet).
	 * Assume it does not die in this case. */
	foreach_out_edge(value, edge) {
		ir_node *user = get_edge_src_irn(edge);
		if (user != here && get_nodes_block(user) == block) {
			return false;
		}
	}
Esempio n. 4
0
/**
 * Compute the height of a node in a block.
 * @param h   The heights object.
 * @param irn The node.
 * @param bl  The block.
 */
static unsigned compute_height(ir_heights_t *h, ir_node *irn, const ir_node *bl)
{
	irn_height_t *ih = get_height_data(h, irn);

	/* bail out if we already visited that node. */
	if (ih->visited >= h->visited)
		return ih->height;

	ih->visited = h->visited;
	ih->height  = 0;

	foreach_out_edge(irn, edge) {
		ir_node *dep = get_edge_src_irn(edge);

		if (!is_Block(dep) && !is_Phi(dep) && get_nodes_block(dep) == bl) {
			unsigned dep_height = compute_height(h, dep, bl);
			ih->height          = MAX(ih->height, dep_height+1);
		}
	}
Esempio n. 5
0
/**
 * tests whether we can legally move node node after node after
 * (only works for nodes in same block)
 */
static bool can_move(ir_node *node, ir_node *after)
{
	ir_node *node_block = get_nodes_block(node);
	assert(node_block == get_nodes_block(after));

	/** all users have to be after the after node */
	foreach_out_edge(node, edge) {
		ir_node *out = get_edge_src_irn(edge);
		if (get_nodes_block(out) != node_block)
			continue;
		/* phi represents a usage at block end */
		if (is_Phi(out))
			continue;
		if (arch_is_irn_not_scheduled(out)) {
			if (!can_move(out, after))
				return false;
		} else {
			if (sched_get_time_step(out) <= sched_get_time_step(after))
				return false;
		}
	}
Esempio n. 6
0
void instrument_initcall(ir_graph *irg, ir_entity *ent)
{
	ir_node        *initial_exec;
	ir_node        *first_block = NULL;
	int             i, idx, need_new_block;
	symconst_symbol sym;

	assure_edges(irg);

	/* find the first block */
	initial_exec = get_irg_initial_exec(irg);

	foreach_out_edge(initial_exec, edge) {
		ir_node *succ = get_edge_src_irn(edge);

		if (is_Block(succ)) {
			/* found the first block */
			first_block = succ;
			break;
		}
	}
Esempio n. 7
0
/**
 * Transforms a Div into the appropriate soft float function.
 */
static bool lower_Div(ir_node *const n)
{
	ir_mode *const mode = get_Div_resmode(n);
	if (!mode_is_float(mode))
		return false;

	ir_node *const left   = get_Div_left(n);
	ir_node *const right  = get_Div_right(n);
	ir_node *const in[]   = { left, right };
	ir_node *const result = make_softfloat_call(n, "div", ARRAY_SIZE(in), in);
	ir_node *const call   = skip_Proj(skip_Proj(result));
	set_irn_pinned(call, get_irn_pinned(n));

	foreach_out_edge_safe(n, edge) {
		ir_node *proj = get_edge_src_irn(edge);
		if (!is_Proj(proj))
			continue;

		switch ((pn_Div)get_Proj_num(proj)) {
		case pn_Div_M:
			set_Proj_pred(proj, call);
			set_Proj_num(proj, pn_Call_M);
			continue;
		case pn_Div_X_regular:
			set_Proj_pred(proj, call);
			set_Proj_num(proj, pn_Call_X_regular);
			continue;
		case pn_Div_X_except:
			set_Proj_pred(proj, call);
			set_Proj_num(proj, pn_Call_X_except);
			continue;
		case pn_Div_res:
			exchange(proj, result);
			continue;
		}
		panic("unexpected Proj number");
	}
Esempio n. 8
0
/**
 * Emit a Compare with conditional branch.
 */
static void emit_amd64_Jcc(const ir_node *irn)
{
	const ir_node      *proj_true  = NULL;
	const ir_node      *proj_false = NULL;
	const ir_node      *block;
	const ir_node      *next_block;
	const char         *suffix;
	const amd64_attr_t *attr      = get_amd64_attr_const(irn);
	ir_relation         relation  = attr->ext.relation;
	ir_node            *op1       = get_irn_n(irn, 0);
	const amd64_attr_t *cmp_attr  = get_amd64_attr_const(op1);
	bool                is_signed = !cmp_attr->data.cmp_unsigned;

	assert(is_amd64_Cmp(op1));

	foreach_out_edge(irn, edge) {
		ir_node *proj = get_edge_src_irn(edge);
		long nr = get_Proj_proj(proj);
		if (nr == pn_Cond_true) {
			proj_true = proj;
		} else {
			proj_false = proj;
		}
	}
Esempio n. 9
0
static void lower_divmod(ir_node *node, ir_node *left, ir_node *right,
                         ir_node *mem, ir_mode *mode, int res_offset)
{
	dbg_info  *dbgi       = get_irn_dbg_info(node);
	ir_node   *block      = get_nodes_block(node);
	ir_node   *left_low   = get_lowered_low(left);
	ir_node   *left_high  = get_lowered_high(left);
	ir_node   *right_low  = get_lowered_low(right);
	ir_node   *right_high = get_lowered_high(right);
	ir_mode   *node_mode  = get_irn_mode(left);
	ir_entity *entity     = mode_is_signed(node_mode) ? ldivmod : uldivmod;
	ir_type   *mtp        = get_entity_type(entity);
	ir_graph  *irg        = get_irn_irg(node);
	ir_node   *addr       = new_r_Address(irg, entity);
	ir_node   *in[4];
	if (arm_cg_config.big_endian) {
		in[0] = left_high;
		in[1] = left_low;
		in[2] = right_high;
		in[3] = right_low;
	} else {
		in[0] = left_low;
		in[1] = left_high;
		in[2] = right_low;
		in[3] = right_high;
	}
	ir_node *call    = new_rd_Call(dbgi, block, mem, addr, ARRAY_SIZE(in), in,
	                               mtp);
	ir_node *resproj = new_r_Proj(call, mode_T, pn_Call_T_result);
	set_irn_pinned(call, get_irn_pinned(node));
	foreach_out_edge_safe(node, edge) {
		ir_node *proj = get_edge_src_irn(edge);
		if (!is_Proj(proj))
			continue;

		switch ((pn_Div)get_Proj_num(proj)) {
		case pn_Div_M:
			/* reroute to the call */
			set_Proj_pred(proj, call);
			set_Proj_num(proj, pn_Call_M);
			break;
		case pn_Div_X_regular:
			set_Proj_pred(proj, call);
			set_Proj_num(proj, pn_Call_X_regular);
			break;
		case pn_Div_X_except:
			set_Proj_pred(proj, call);
			set_Proj_num(proj, pn_Call_X_except);
			break;
		case pn_Div_res: {
			ir_mode *low_mode = get_irn_mode(left_low);
			if (arm_cg_config.big_endian) {
				ir_node *res_low  = new_r_Proj(resproj, low_mode, res_offset+1);
				ir_node *res_high = new_r_Proj(resproj, mode,     res_offset);
				ir_set_dw_lowered(proj, res_low, res_high);
			} else {
				ir_node *res_low  = new_r_Proj(resproj, low_mode, res_offset);
				ir_node *res_high = new_r_Proj(resproj, mode,     res_offset+1);
				ir_set_dw_lowered(proj, res_low, res_high);
			}
			break;
		}
		}
		/* mark this proj: we have handled it already, otherwise we might fall
		 * into out new nodes. */
		mark_irn_visited(proj);
	}