Exemplo n.º 1
0
/**
 * analyze enough to decide if we should lower the switch
 */
static void analyse_switch0(switch_info_t *info, ir_node *switchn)
{
	const ir_switch_table *table      = get_Switch_table(switchn);
	size_t                 n_entries  = ir_switch_table_get_n_entries(table);
	ir_mode               *mode       = get_irn_mode(get_Switch_selector(switchn));
	ir_tarval             *switch_min = get_mode_max(mode);
	ir_tarval             *switch_max = get_mode_min(mode);
	unsigned               num_cases  = 0;

	for (size_t e = 0; e < n_entries; ++e) {
		const ir_switch_table_entry *entry
			= ir_switch_table_get_entry_const(table, e);
		if (entry->pn == pn_Switch_default)
			continue;

		if (tarval_cmp(entry->min, switch_min) == ir_relation_less)
			switch_min = entry->min;
		if (tarval_cmp(entry->max, switch_max) == ir_relation_greater)
			switch_max = entry->max;

		++num_cases;
	}

	info->switchn    = switchn;
	info->switch_min = switch_min;
	info->switch_max = switch_max;
	info->num_cases  = num_cases;
}
Exemplo n.º 2
0
bool enum_bitfield_big_enough(enum_t *enume, type_t *base_type,
                              unsigned bitfield_size)
{
	ir_mode    *mode        = get_ir_mode_storage(base_type);
	ir_tarval  *max         = get_mode_max(mode);
	ir_tarval  *min         = get_mode_min(mode);
	bool       is_signed    = is_type_signed(base_type);
	unsigned   mode_size    = get_mode_size_bits(mode);
	unsigned   shift_amount = mode_size - bitfield_size + is_signed;
	ir_tarval *adjusted_max;
	ir_tarval *adjusted_min;
	/* corner case: signed mode with just sign bit results in shift_amount
	 * being as big as mode_size triggering "modulo shift" which is not what
	 * we want here. */
	if (shift_amount >= mode_size) {
		assert(bitfield_size == 1 && mode_is_signed(mode));
		adjusted_max = get_mode_null(mode);
		adjusted_min = get_mode_all_one(mode);
	} else {
		adjusted_max = tarval_shr_unsigned(max, shift_amount);
		adjusted_min = tarval_shrs_unsigned(min, shift_amount);
	}

	for (entity_t *entry = enume->first_value;
	     entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
	     entry = entry->base.next) {
		ir_tarval *tv = get_enum_value(&entry->enum_value);
		if (tv == NULL)
			continue;
		ir_tarval *tvc = tarval_convert_to(tv, mode);
		if (tarval_cmp(tvc, adjusted_min) == ir_relation_less
		 || tarval_cmp(tvc, adjusted_max) == ir_relation_greater) {
			return false;
		}
	}
	return true;
}
Exemplo n.º 3
0
static ir_tarval *fold_binary_comparison(
		binary_expression_t const *const binexpr)
{
	ir_tarval   *const left   = fold_expression(binexpr->left);
	ir_tarval   *const right  = fold_expression(binexpr->right);
	type_t      *const atype  = skip_typeref(binexpr->left->base.type);
	ir_mode     *const amode  = get_ir_mode_arithmetic(atype);
	assert(amode == get_ir_mode_arithmetic(skip_typeref(binexpr->right->base.type)));
	ir_tarval   *const lefta  = tarval_convert_to(left, amode);
	ir_tarval   *const righta = tarval_convert_to(right, amode);

	type_t      *const type = skip_typeref(binexpr->base.type);
	ir_mode     *const mode = get_ir_mode_arithmetic(type);
	ir_relation  const rel  = get_relation(binexpr->base.kind);
	return create_tarval_from_bool(mode, tarval_cmp(lefta, righta) & rel);
}
Exemplo n.º 4
0
/*
 * Check, if the value of a node is != 0.
 *
 * This is a often needed case, so we handle here Confirm
 * nodes too.
 */
int value_not_zero(const ir_node *n, const ir_node **confirm)
{
#define RET_ON(x)  if (x) { *confirm = n; return 1; } break

	ir_tarval *tv;
	ir_mode *mode = get_irn_mode(n);
	ir_relation relation;

	*confirm = NULL;

	/* there might be several Confirms one after other that form an interval */
	for (;;) {
		if (is_Minus(n)) {
			/* we can safely skip Minus when checking for != 0 */
			n = get_Minus_op(n);
			continue;
		}
		if (! is_Confirm(n))
			break;

		/*
		 * Note: A Confirm is never after a Const. So,
		 * we simply can check the bound for being a Const
		 * without the fear that is might be hidden by a further Confirm.
		 */
		tv = value_of(get_Confirm_bound(n));
		if (tv == tarval_bad) {
			n = get_Confirm_value(n);
			continue;
		}

		relation = tarval_cmp(tv, get_mode_null(mode));

		/*
		 * Beware: C might by a NaN. It is not clear, what we should do
		 * than. Of course a NaN is != 0, but we might use this function
		 * to remove up Exceptions, and NaN's might generate Exception.
		 * So, we do NOT handle NaNs here for safety.
		 *
		 * Note that only the C != 0 case need additional checking.
		 */
		switch (get_Confirm_relation(n)) {
		case ir_relation_equal: /* n == C /\ C != 0 ==> n != 0 */
			RET_ON(relation != ir_relation_equal && relation != ir_relation_unordered);
		case ir_relation_less_greater: /* n != C /\ C == 0 ==> n != 0 */
			RET_ON(relation == ir_relation_equal);
		case ir_relation_less: /* n <  C /\ C <= 0 ==> n != 0 */
			RET_ON(relation == ir_relation_less || relation == ir_relation_equal);
		case ir_relation_less_equal: /* n <= C /\ C <  0 ==> n != 0 */
			RET_ON(relation == ir_relation_less);
		case ir_relation_greater_equal: /* n >= C /\ C >  0 ==> n != 0 */
			RET_ON(relation == ir_relation_greater);
		case ir_relation_greater: /* n >  C /\ C >= 0 ==> n != 0 */
			RET_ON(relation == ir_relation_greater || relation == ir_relation_equal);
		default:
			break;
		}
		n = get_Confirm_value(n);
	}
	/* global entities are never NULL */
	if (is_SymConst_addr_ent(n))
		return true;

	tv = value_of(n);
	if (tv == tarval_bad)
		return false;

	relation = tarval_cmp(tv, get_mode_null(mode));

	/* again, need check for NaN */
	return (relation != ir_relation_equal) && (relation != ir_relation_unordered);

#undef RET_ON
}
Exemplo n.º 5
0
/**
 * Try to evaluate l_iv relation r_iv.
 *
 * @param l_iv      the left interval
 * @param r_iv      the right interval
 * @param relation  the compare relation
 *
 * @return
 *   tarval_b_true or tarval_b_false it it can be evaluated,
 *   tarval_bad else
 */
static ir_tarval *(compare_iv)(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation)
{
	ir_relation res;
	unsigned    flags;
	ir_tarval  *tv_true = tarval_b_true, *tv_false = tarval_b_false;

	/* if one interval contains NaNs, we cannot evaluate anything */
	if (! l_iv || ! r_iv)
		return tarval_bad;

	/* we can only check ordered relations */
	if (relation & ir_relation_unordered) {
		ir_tarval *t;

		relation = get_negated_relation(relation);
		t        = tv_true;
		tv_true  = tv_false;
		tv_false = t;
	}

	/* if we have > or >=, we do the inverse to save some cases */
	if (relation == ir_relation_greater_equal || relation == ir_relation_greater) {
		const interval_t *t;

		relation = get_inversed_relation(relation);
		t        = l_iv;
		l_iv     = r_iv;
		r_iv     = t;
	}

	/* now, only the following cases remains */
	switch (relation) {
	case ir_relation_equal:
		/* two intervals can be compared for equality only if they are a single value */
		if (l_iv->min == l_iv->max && r_iv->min == r_iv->max)
			return tarval_cmp(l_iv->min, r_iv->min) == ir_relation_equal ? tv_true : tv_false;

		/* if both intervals do not intersect, it is never equal */
		res = tarval_cmp(l_iv->max, r_iv->min);

		/* b < c ==> [a,b] != [c,d] */
		if (res == ir_relation_less)
			return tv_false;

		/* b <= c ==> [a,b) != [c,d]  AND [a,b] != (c,d] */
		if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED)
			&& (res == ir_relation_equal))
			return tv_false;

		res = tarval_cmp(r_iv->max, l_iv->min);

		/* d < a ==> [c,d] != [a,b] */
		if (res == ir_relation_less)
			return tv_false;

		/* d <= a ==> [c,d) != [a,b]  AND [c,d] != (a,b] */
		if ((r_iv->flags & MAX_EXCLUDED || l_iv->flags & MIN_EXCLUDED)
			&& (res == ir_relation_equal))
			return tv_false;
		break;

	case ir_relation_less_greater:
		/* two intervals can be compared for not equality only if they are a single value */
		if (l_iv->min == l_iv->max && r_iv->min == r_iv->max)
			return tarval_cmp(l_iv->min, r_iv->min) != ir_relation_equal ? tv_true : tv_false;
		break;

	case ir_relation_less:
		res = tarval_cmp(l_iv->max, r_iv->min);

		/* [a, b] < [c, d]  <==> b < c */
		if (res == ir_relation_less)
			return tv_true;

		/* if one border is excluded, b <= c is enough */
		if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED) &&
			res == ir_relation_equal)
			return tv_true;

		/* [a, b] >= [c, d] <==> a > d */
		res = tarval_cmp(l_iv->min, r_iv->max);
		if (res == ir_relation_greater)
			return tv_false;

		/* if one border is excluded, a >= d is enough */
		if ((l_iv->flags & MIN_EXCLUDED || r_iv->flags & MAX_EXCLUDED) &&
			res == ir_relation_equal)
			return tv_false;
		break;

	case ir_relation_less_equal:
		/* [a, b) <= [c, d] or [a, b] <= (c, d]  <==> b <= c */
		flags = (l_iv->flags & MAX_EXCLUDED) | (r_iv->flags & MIN_EXCLUDED);
		if (flags) {
			res = tarval_cmp(l_iv->max, r_iv->min);

			if (res == ir_relation_less || res == ir_relation_equal)
				return tv_true;
		}

		res = tarval_cmp(l_iv->min, r_iv->max);

		/* [a, b] > [c, d] <==> a > d */
		if (res == ir_relation_greater)
			return tv_false;

		/* if one border is excluded, a >= d is enough */
		if ((l_iv->flags & MIN_EXCLUDED || r_iv->flags & MAX_EXCLUDED) &&
			res == ir_relation_equal)
			return tv_false;
		break;

	case ir_relation_less_equal_greater:
		/* Hmm. if both are intervals, we can find an order */
		return tv_true;

	default:
		return tarval_bad;
	}
	return tarval_bad;
}
Exemplo n.º 6
0
/*
 * 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;
	}
}