コード例 #1
0
ファイル: proc_cloning.c プロジェクト: dianpeng/libfirm
/**
 * Copies a node to a new irg. The Ins of the new node point to
 * the predecessors on the old irg.  n->link points to the new node.
 *
 * @param n    The node to be copied
 * @param irg  the new irg
 *
 * Does NOT copy standard nodes like Start, End etc that are fixed
 * in an irg. Instead, the corresponding nodes of the new irg are returned.
 * Note further, that the new nodes have no block.
 */
static void copy_irn_to_irg(ir_node *n, ir_graph *irg)
{
    /* do not copy standard nodes */
    ir_node *nn = NULL;
    switch (get_irn_opcode(n)) {
    case iro_NoMem:
        nn = get_irg_no_mem(irg);
        break;

    case iro_Block: {
        ir_graph *old_irg = get_irn_irg(n);
        if (n == get_irg_start_block(old_irg))
            nn = get_irg_start_block(irg);
        else if (n == get_irg_end_block(old_irg))
            nn = get_irg_end_block(irg);
        break;
    }

    case iro_Start:
        nn = get_irg_start(irg);
        break;

    case iro_End:
        nn = get_irg_end(irg);
        break;

    case iro_Proj: {
        ir_graph *old_irg = get_irn_irg(n);
        if (n == get_irg_frame(old_irg))
            nn = get_irg_frame(irg);
        else if (n == get_irg_initial_mem(old_irg))
            nn = get_irg_initial_mem(irg);
        else if (n == get_irg_args(old_irg))
            nn = get_irg_args(irg);
        break;
    }
    }

    if (nn) {
        set_irn_link(n, nn);
        return;
    }

    nn = new_ir_node(get_irn_dbg_info(n),
                     irg,
                     NULL,            /* no block yet, will be set later */
                     get_irn_op(n),
                     get_irn_mode(n),
                     get_irn_arity(n),
                     get_irn_in(n));


    /* Copy the attributes.  These might point to additional data.  If this
       was allocated on the old obstack the pointers now are dangling.  This
       frees e.g. the memory of the graph_arr allocated in new_immBlock. */
    copy_node_attr(irg, n, nn);
    set_irn_link(n, nn);
}
コード例 #2
0
static bool eat_imm(x86_address_t *const addr, ir_node const *const node,
                    bool basereg_usable)
{
	switch (get_irn_opcode(node)) {
	case iro_Add:
		/* Add is supported as long as both operands are immediates. */
		return
			!x86_is_non_address_mode_node(node) &&
			eat_imm(addr, get_Add_left(node), basereg_usable) &&
			eat_imm(addr, get_Add_right(node), basereg_usable);

	case iro_Address:
		/* The first Address of a DAG can be folded into an immediate. */
		if (addr->imm.entity)
			return false;
		addr->imm.entity = get_Address_entity(node);
		addr->imm.kind = X86_IMM_ADDR;
		if (is_tls_entity(addr->imm.entity))
			addr->tls_segment = true;
		return true;

	case iro_Const: {
		/* Add the value to the offset. */
		ir_tarval *const tv = get_Const_tarval(node);
		if (!tarval_possible(tv))
			return false;
		addr->imm.offset += get_tarval_long(tv);
		return true;
	}

	case iro_Unknown:
		/* Use '0' for Unknowns. */
		return true;

	default:
		if (be_is_Relocation(node)) {
			if (addr->imm.entity)
				return false;
			addr->imm.entity = be_get_Relocation_entity(node);
			x86_immediate_kind_t const kind
				= (x86_immediate_kind_t)be_get_Relocation_kind(node);
			addr->imm.kind = kind;
			if (kind == X86_IMM_GOTPCREL || kind == X86_IMM_PCREL) {
				if (!basereg_usable)
					return false;
				addr->ip_base = true;
			}
			return true;
		}
		/* All other nodes are no immediates. */
		return false;
	}
}
コード例 #3
0
ファイル: lower_hl.c プロジェクト: qznc/libfirm
/**
 * lowers IR-nodes, called from walker
 */
static void lower_irnode(ir_node *irn, void *env)
{
	(void) env;
	switch (get_irn_opcode(irn)) {
	case iro_Sel:
		lower_sel(irn);
		break;
	case iro_SymConst:
		lower_symconst(irn);
		break;
	default:
		break;
	}
}
コード例 #4
0
ファイル: irbackedge.c プロジェクト: lu-zero/libfirm
/**
 * Returns backarray if the node can have backedges, else returns
 * NULL.
 *
 * Does not assert whether the backarray is correct -- use
 * very careful!
 */
static bitset_t *mere_get_backarray(const ir_node *n)
{
	switch (get_irn_opcode(n)) {
	case iro_Block:
		if (!get_Block_matured(n))
			return NULL;

		assert(n->attr.block.backedge != NULL);
		return n->attr.block.backedge;
	case iro_Phi:
		assert(n->attr.phi.u.backedge != NULL);
		return n->attr.phi.u.backedge;
	default:
		break;
	}
	return NULL;
}
コード例 #5
0
ファイル: entity.c プロジェクト: qznc/libfirm
int is_irn_const_expression(ir_node *n)
{
	/* we are in danger iff an exception will arise. TODO: be more precisely,
	 * for instance Div. will NOT rise if divisor != 0 */
	if (is_binop(n) && !is_fragile_op(n))
		return is_irn_const_expression(get_binop_left(n)) && is_irn_const_expression(get_binop_right(n));

	switch (get_irn_opcode(n)) {
	case iro_Const:
	case iro_SymConst:
	case iro_Unknown:
		return 1;
	case iro_Conv:
		return is_irn_const_expression(get_irn_n(n, 0));
	default:
		break;
	}
	return 0;
}
コード例 #6
0
ファイル: beinfo.c プロジェクト: lamproae/libfirm
void be_info_new_node(ir_graph *irg, ir_node *node)
{
	/* Projs need no be info, all info is fetched from their predecessor */
	if (is_Proj(node))
		return;

	struct obstack *obst = be_get_be_obst(irg);
	backend_info_t *info = OALLOCZ(obst, backend_info_t);

	assert(node->backend_info == NULL);
	node->backend_info = info;

	/*
	 * Set backend info for some middleend nodes which still appear in
	 * backend graphs
	 */
	arch_irn_flags_t           flags = arch_irn_flag_not_scheduled;
	arch_register_req_t const *req   = arch_no_register_req;
	switch (get_irn_opcode(node)) {
	case iro_Block:
	case iro_Dummy:
	case iro_Anchor:
	case iro_Bad:
	case iro_End:
	case iro_Unknown:
		break;
	case iro_NoMem:
	case iro_Pin:
	case iro_Sync:
		req = arch_memory_req;
		break;
	case iro_Phi:
		flags = arch_irn_flag_schedule_first;
		break;
	default:
		return;
	}

	info->flags     = flags;
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, 1);
	info->out_infos[0].req = req;
}
コード例 #7
0
ファイル: irbackedge.c プロジェクト: lu-zero/libfirm
void fix_backedges(struct obstack *obst, ir_node *n)
{
	bitset_t *arr = mere_get_backarray(n);
	if (arr == NULL)
		return;

	int arity = get_irn_arity(n);
	if (bitset_size(arr) != (unsigned) arity) {
		arr = new_backedge_arr(obst, arity);

		unsigned opc = get_irn_opcode(n);
		if (opc == iro_Phi)
			n->attr.phi.u.backedge = arr;
		else if (opc == iro_Block) {
			n->attr.block.backedge = arr;
		}
	}

	assert(legal_backarray(n));
}
コード例 #8
0
ファイル: opt_confirms.c プロジェクト: qznc/libfirm
/*
 * Check, if the value of a node can be confirmed >= 0 or <= 0,
 * If the mode of the value did not honor signed zeros, else
 * check for >= 0 or < 0.
 */
ir_value_classify_sign classify_value_sign(ir_node *n)
{
	ir_tarval *tv, *c;
	ir_mode *mode;
	ir_relation cmp, ncmp;
	int negate = 1;

	for (;;) {
		unsigned code = get_irn_opcode(n);

		switch (code) {
		case iro_Minus:
			negate *= -1;
			n = get_Minus_op(n);
			continue;
		case iro_Confirm:
			break;
		default:
			return value_classified_unknown;
		}
		break;
	}
	if (!is_Confirm(n))
		return value_classified_unknown;

	tv  = value_of(get_Confirm_bound(n));
	if (tv == tarval_bad)
		return value_classified_unknown;

	mode = get_irn_mode(n);

	/*
	 * We can handle only >=, >, <, <= cases.
	 * We could handle == too, but this will be optimized into
	 * a constant either.
	 *
	 * Note that for integer modes we have a slightly better
	 * optimization possibilities, so we handle this
	 * different.
	 */
	cmp = get_Confirm_relation(n);

	switch (cmp) {
	case ir_relation_less:
		/*
		 * must be x < c <= 1 to be useful if integer mode and -0 = 0
		 *         x < c <= 0 to be useful else
		 */
	case ir_relation_less_equal:
		/*
		 * must be x <= c < 1 to be useful if integer mode and -0 = 0
		 *         x <= c < 0 to be useful else
		 */
		c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ?
			get_mode_one(mode) : get_mode_null(mode);

		ncmp = tarval_cmp(tv, c);
		if (ncmp == ir_relation_equal)
			ncmp = ir_relation_less_equal;

		if (cmp != (ncmp ^ ir_relation_equal))
			return value_classified_unknown;

		/* yep, negative */
		return value_classified_negative * negate;

	case ir_relation_greater_equal:
		/*
		 * must be x >= c > -1 to be useful if integer mode
		 *         x >= c >= 0 to be useful else
		 */
	case ir_relation_greater:
		/*
		 * must be x > c >= -1 to be useful if integer mode
		 *         x > c >= 0 to be useful else
		 */
		if (mode_is_int(mode)) {
			c = get_mode_minus_one(mode);

			ncmp = tarval_cmp(tv, c);
			if (ncmp == ir_relation_equal)
				ncmp = ir_relation_greater_equal;

			if (cmp != (ncmp ^ ir_relation_equal))
				return value_classified_unknown;
		} else {
			c = get_mode_minus_one(mode);

			ncmp = tarval_cmp(tv, c);

			if (ncmp != ir_relation_equal && ncmp != ir_relation_greater)
				return value_classified_unknown;
		}

		/* yep, positive */
		return value_classified_positive * negate;

	default:
		return value_classified_unknown;
	}
}
コード例 #9
0
ファイル: lower_softfloat.c プロジェクト: lamproae/libfirm
/**
 * @return The type of the function replacing the given node.
 */
static ir_type *get_softfloat_type(const ir_node *n)
{
	ir_node *operand      = get_irn_n(n, 0);
	ir_mode *operand_mode = get_irn_mode(operand);

	switch (get_irn_opcode(n)) {
	case iro_Div:
		operand_mode = get_irn_mode(get_Div_left(n));
		/* fall through */
	case iro_Add:
	case iro_Mul:
	case iro_Sub:
		if (operand_mode == mode_F)
			return binop_tp_f;
		else if (operand_mode == mode_D)
			return binop_tp_d;
		break;
	case iro_Cmp:
		if (operand_mode == mode_F)
			return cmp_tp_f;
		else if (operand_mode == mode_D)
			return cmp_tp_d;
		break;

	case iro_Conv: {
		ir_mode *const mode = get_irn_mode(n);
		if (operand_mode == mode_D) {
			if (mode == mode_F)
				return unop_tp_d_f;
			else if (get_mode_arithmetic(mode) == irma_twos_complement) {
				if (get_mode_size_bits(mode) <= 32)
					return mode_is_signed(mode) ? unop_tp_d_is : unop_tp_d_iu;
				else if (get_mode_size_bits(mode) == 64)
					return mode_is_signed(mode) ? unop_tp_d_ls : unop_tp_d_lu;
			}
		} else if (operand_mode == mode_F) {
			if (mode == mode_D)
				return unop_tp_f_d;
			else if (get_mode_arithmetic(mode) == irma_twos_complement) {
				if (get_mode_size_bits(mode) <= 32)
					return mode_is_signed(mode) ? unop_tp_f_is : unop_tp_f_iu;
				else if (get_mode_size_bits(mode) == 64)
					return mode_is_signed(mode) ? unop_tp_f_ls : unop_tp_f_lu;
			}
		} else if (get_mode_arithmetic(operand_mode) == irma_twos_complement) {
			if (mode_is_signed(operand_mode)) {
				if (get_mode_size_bits(operand_mode) <= 32) {
					if (mode == mode_D)
						return unop_tp_is_d;
					else if (mode == mode_F)
						return unop_tp_is_f;
				} else if (get_mode_size_bits(operand_mode) == 64) {
					if (mode == mode_D)
						return unop_tp_ls_d;
					else if (mode == mode_F)
						return unop_tp_ls_f;
				}
			} else {
				if (get_mode_size_bits(operand_mode) <= 32) {
					if (mode == mode_D)
						return unop_tp_iu_d;
					else if (mode == mode_F)
						return unop_tp_iu_f;
				} else if (get_mode_size_bits(operand_mode) == 64) {
					if (mode == mode_D)
						return unop_tp_lu_d;
					else if (mode == mode_F)
						return unop_tp_lu_f;
				}
			}
		}
		break;
	}

	case iro_Minus:
		if (operand_mode == mode_F)
			return unop_tp_f;
		else if (operand_mode == mode_D)
			return unop_tp_d;
		break;
	default: break;
	}

	panic("could not determine a suitable type");
}
コード例 #10
0
ファイル: entity.c プロジェクト: qznc/libfirm
ir_node *copy_const_value(dbg_info *dbg, ir_node *n, ir_node *block)
{
	ir_graph *irg = get_irn_irg(block);

	/* @@@ GL I think we should implement this using the routines from irgopt
	 * for dead node elimination/inlineing. */
	ir_mode *m = get_irn_mode(n);
	ir_node *nn;
	switch (get_irn_opcode(n)) {
	case iro_Const:
		nn = new_rd_Const(dbg, irg, get_Const_tarval(n));
		break;
	case iro_SymConst:
		nn = new_rd_SymConst(dbg, irg, get_irn_mode(n), get_SymConst_symbol(n), get_SymConst_kind(n));
		break;
	case iro_Add:
		nn = new_rd_Add(dbg, block,
		                copy_const_value(dbg, get_Add_left(n), block),
		                copy_const_value(dbg, get_Add_right(n), block), m);
		break;
	case iro_Sub:
		nn = new_rd_Sub(dbg, block,
		                copy_const_value(dbg, get_Sub_left(n), block),
		                copy_const_value(dbg, get_Sub_right(n), block), m);
		break;
	case iro_Mul:
		nn = new_rd_Mul(dbg, block,
		                copy_const_value(dbg, get_Mul_left(n), block),
		                copy_const_value(dbg, get_Mul_right(n), block), m);
		break;
	case iro_And:
		nn = new_rd_And(dbg, block,
		                copy_const_value(dbg, get_And_left(n), block),
		                copy_const_value(dbg, get_And_right(n), block), m);
		break;
	case iro_Or:
		nn = new_rd_Or(dbg, block,
		               copy_const_value(dbg, get_Or_left(n), block),
		               copy_const_value(dbg, get_Or_right(n), block), m);
		break;
	case iro_Eor:
		nn = new_rd_Eor(dbg, block,
		                copy_const_value(dbg, get_Eor_left(n), block),
		                copy_const_value(dbg, get_Eor_right(n), block), m);
		break;
	case iro_Conv:
		nn = new_rd_Conv(dbg, block,
		                 copy_const_value(dbg, get_Conv_op(n), block), m);
		break;
	case iro_Minus:
		nn = new_rd_Minus(dbg, block,
		                  copy_const_value(dbg, get_Minus_op(n), block), m);
		break;
	case iro_Not:
		nn = new_rd_Not(dbg, block,
		                copy_const_value(dbg, get_Not_op(n), block), m);
		break;
	case iro_Unknown:
		nn = new_r_Unknown(irg, m);
		break;
	default:
		panic("opcode invalid or not implemented %+F", n);
	}
	return nn;
}
コード例 #11
0
ファイル: analyze_irg_args.c プロジェクト: lu-zero/libfirm
/**
 * Walk recursive the successors of a graph argument
 * with mode reference and mark if it will be read,
 * written or stored.
 *
 * @param arg   The graph argument with mode reference,
 *             that must be checked.
 */
static ptr_access_kind analyze_arg(ir_node *arg, ptr_access_kind bits)
{
	/* We must visit a node once to avoid endless recursion.*/
	mark_irn_visited(arg);

	for (int i = get_irn_n_outs(arg); i-- > 0; ) {
		ir_node *succ = get_irn_out(arg, i);
		if (irn_visited(succ))
			continue;

		/* We should not walk over the memory edge.*/
		if (get_irn_mode(succ) == mode_M)
			continue;

		/* If we reach with the recursion a Call node and our reference
		   isn't the address of this Call we accept that the reference will
		   be read and written if the graph of the method represented by
		   "Call" isn't computed else we analyze that graph. If our
		   reference is the address of this
		   Call node that mean the reference will be read.*/
		switch (get_irn_opcode(succ)) {

		case iro_Call: {
			ir_node *ptr  = get_Call_ptr(succ);

			if (ptr == arg) {
				/* Hmm: not sure what this is, most likely a read */
				bits |= ptr_access_read;
			} else {
				ir_entity *meth_ent;

				if (is_SymConst_addr_ent(ptr)) {
					meth_ent = get_SymConst_entity(ptr);

					for (int p = get_Call_n_params(succ); p-- > 0; ) {
						if (get_Call_param(succ, p) == arg) {
							/* an arg can be used more than once ! */
							bits |= get_method_param_access(meth_ent, p);
						}
					}
				} else if (is_Sel(ptr) && get_irp_callee_info_state() == irg_callee_info_consistent) {
					/* is be a polymorphic call but callee information is available */
					size_t n_params = get_Call_n_params(succ);

					/* simply look into ALL possible callees */
					for (int c = get_Call_n_callees(succ); c-- > 0; ) {
						meth_ent = get_Call_callee(succ, c);

						/* unknown_entity is used to signal that we don't know what is called */
						if (is_unknown_entity(meth_ent)) {
							bits |= ptr_access_all;
							break;
						}

						for (size_t p = n_params; p-- > 0; ) {
							if (get_Call_param(succ, p) == arg) {
								/* an arg can be used more than once ! */
								bits |= get_method_param_access(meth_ent, p);
							}
						}
					}
				} else /* can do anything */
					bits |= ptr_access_all;
			}

			/* search stops here anyway */
			continue;
		}
		case iro_Store:
			/* We have reached a Store node => the reference is written or stored. */
			if (get_Store_ptr(succ) == arg) {
				/* written to */
				bits |= ptr_access_write;
			} else {
				/* stored itself */
				bits |= ptr_access_store;
			}

			/* search stops here anyway */
			continue;

		case iro_Load:
			/* We have reached a Load node => the reference is read. */
			bits |= ptr_access_read;

			/* search stops here anyway */
			continue;

		case iro_Conv:
			/* our address is casted into something unknown. Break our search. */
			bits = ptr_access_all;
			break;

		default:
			break;
		}

		/* If we know that, the argument will be read, write and stored, we
		   can break the recursion.*/
		if (bits == ptr_access_all) {
			bits = ptr_access_all;
			break;
		}

		/*
		 * A calculation that do not lead to a reference mode ends our search.
		 * This is dangerous: It would allow to cast into integer and that cast back ...
		 * so, when we detect a Conv we go mad, see the Conv case above.
		 */
		if (!mode_is_reference(get_irn_mode(succ)))
			continue;

		/* follow further the address calculation */
		bits = analyze_arg(succ, bits);
	}
	set_irn_link(arg, NULL);
	return bits;
}
コード例 #12
0
ファイル: analyze_irg_args.c プロジェクト: lu-zero/libfirm
/**
 * Compute the weight of a method parameter
 *
 * @param arg  The parameter them weight muss be computed.
 */
static unsigned calc_method_param_weight(ir_node *arg)
{
	/* We mark the nodes to avoid endless recursion */
	mark_irn_visited(arg);

	unsigned weight = null_weight;
	for (int i = get_irn_n_outs(arg); i-- > 0; ) {
		ir_node *succ = get_irn_out(arg, i);
		if (irn_visited(succ))
			continue;

		/* We should not walk over the memory edge.*/
		if (get_irn_mode(succ) == mode_M)
			continue;

		switch (get_irn_opcode(succ)) {
		case iro_Call:
			if (get_Call_ptr(succ) == arg) {
				/* the arguments is used as an pointer input for a call,
				   we can probably change an indirect Call into a direct one. */
				weight += indirect_call_weight;
			}
			break;
		case iro_Cmp: {
			/* We have reached a cmp and we must increase the
			   weight with the cmp_weight. */
			ir_node *op;
			if (get_Cmp_left(succ) == arg)
				op = get_Cmp_right(succ);
			else
				op = get_Cmp_left(succ);

			if (is_irn_constlike(op)) {
				weight += const_cmp_weight;
			} else
				weight += cmp_weight;
			break;
		}
		case iro_Cond:
			/* the argument is used for a SwitchCond, a big win */
			weight += const_cmp_weight * get_irn_n_outs(succ);
			break;
		case iro_Id:
			/* when looking backward we might find Id nodes */
			weight += calc_method_param_weight(succ);
			break;
		case iro_Tuple:
			/* unoptimized tuple */
			for (int j = get_Tuple_n_preds(succ); j-- > 0; ) {
				ir_node *pred = get_Tuple_pred(succ, j);
				if (pred == arg) {
					/* look for Proj(j) */
					for (int k = get_irn_n_outs(succ); k-- > 0; ) {
						ir_node *succ_succ = get_irn_out(succ, k);
						if (is_Proj(succ_succ)) {
							if (get_Proj_proj(succ_succ) == j) {
								/* found */
								weight += calc_method_param_weight(succ_succ);
							}
						} else {
							/* this should NOT happen */
						}
					}
				}
			}
			break;
		default:
			if (is_binop(succ)) {
				/* We have reached a BinOp and we must increase the
				   weight with the binop_weight. If the other operand of the
				   BinOp is a constant we increase the weight with const_binop_weight
				   and call the function recursive.
				 */
				ir_node *op;
				if (get_binop_left(succ) == arg)
					op = get_binop_right(succ);
				else
					op = get_binop_left(succ);

				if (is_irn_constlike(op)) {
					weight += const_binop_weight;
					weight += calc_method_param_weight(succ);
				} else
					weight += binop_weight;
			} else if (get_irn_arity(succ) == 1) {
				/* We have reached a binop and we must increase the
				   weight with the const_binop_weight and call the function
				   recursive.*/
				weight += const_binop_weight;
				weight += calc_method_param_weight(succ);
			}
			break;
		}
	}
	set_irn_link(arg, NULL);
	return weight;
}