예제 #1
0
/**
 * Transforms a Cmp into the appropriate soft float function.
 */
static bool lower_Cmp(ir_node *const n)
{
	ir_node *const left    = get_Cmp_left(n);
	ir_mode *const op_mode = get_irn_mode(left);
	if (!mode_is_float(op_mode))
		return false;

	dbg_info *const dbgi = get_irn_dbg_info(n);
	ir_graph *const irg  = get_irn_irg(n);
	ir_node  *const zero = new_rd_Const_null(dbgi, irg, mode_Is);

	char const  *name     = NULL;
	char const  *name2    = NULL;
	ir_node     *result   = NULL;
	ir_relation  relation = get_Cmp_relation(n);
	switch (relation) {
	case ir_relation_false:
		result = zero;
		break;
	case ir_relation_equal:
		name = "eq";
		break;
	case ir_relation_less:
		name = "lt";
		break;
	case ir_relation_greater:
		name = "gt";
		break;
	case ir_relation_unordered:
		name     = "unord";
		relation = ir_relation_less_greater;
		break;
	case ir_relation_less_equal:
		name = "le";
		break;
	case ir_relation_greater_equal:
		name = "ge";
		break;
	case ir_relation_less_greater:
		name  = "unord";
		name2 = "ne";
		break;
	case ir_relation_less_equal_greater:
		name     = "unord";
		relation = ir_relation_equal;
		break;
	case ir_relation_unordered_equal:
		name     = "unord";
		relation = ir_relation_less_greater;
		name2    = "ne";
		break;
	case ir_relation_unordered_less:
		name     = "ge";
		relation = ir_relation_less;
		break;
	case ir_relation_unordered_less_equal:
		name     = "gt";
		relation = ir_relation_less_equal;
		break;
	case ir_relation_unordered_greater:
		name     = "le";
		relation = ir_relation_greater;
		break;
	case ir_relation_unordered_greater_equal:
		name     = "lt";
		relation = ir_relation_greater_equal;
		break;
	case ir_relation_unordered_less_greater:
		name     = "eq";
		relation = ir_relation_less_greater;
		break;
	case ir_relation_true:
		result = zero;
		break;
	}

	ir_node *const block = get_nodes_block(n);
	ir_node *const right = get_Cmp_right(n);

	if (result == NULL) {
		ir_node *const in[] = { left, right };
		result = make_softfloat_call(n, name, ARRAY_SIZE(in), in);
	}

	ir_node *cmp = new_r_Cmp(block, result, zero, relation);

	/* We need two calls into the softfloat library */
	if (name2 != NULL) {
		ir_node *const in[] = { left, right };
		result   = make_softfloat_call(n, name2, ARRAY_SIZE(in), in);
		relation = get_Cmp_relation(n);

		ir_node *const mux = new_rd_Mux(dbgi, block, cmp, result, zero);

		arch_allow_ifconv_func const allow_ifconv
			= be_get_backend_param()->allow_ifconv;
		if (!allow_ifconv(cmp, result, zero))
			ir_nodeset_insert(&created_mux_nodes, mux);

		cmp = new_r_Cmp(block, mux, zero, relation);
	}

	exchange(n, cmp);
	return true;
}
예제 #2
0
/**
 * 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;
}