/**
* Sets the overflow mode for integer operations.
+ *
+ * @param ov_mode one of teh overflow modes
*/
void tarval_set_integer_overflow_mode(tarval_int_overflow_mode_t ov_mode);
* The sort member of the struct mode defines which operations are valid
*/
-/** Bitwise Negation of a tarval. */
+/**
+ * Bitwise Negation of a tarval.
+ *
+ * @param a the first tarval
+ *
+ * @return ~a or tarval_bad
+ */
tarval *tarval_not(tarval *a);
-/** Arithmetic Negation of a tarval. */
+/**
+ * Arithmetic Negation of a tarval.
+ *
+ * @param a the first tarval
+ *
+ * @return -a or tarval_bad
+ */
tarval *tarval_neg(tarval *a);
-/** Addition of two tarvals. */
+/**
+ * Addition of two tarvals.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a + b or tarval_bad
+ */
tarval *tarval_add(tarval *a, tarval *b);
-/** Subtraction from a tarval. */
-tarval *tarval_sub(tarval *a, tarval *b);
+/**
+ * Subtraction from a tarval.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ * @param dst_mode the mode of the result, needed for mode_P - mode_P, else NULL
+ *
+ * @return a - b or tarval_bad
+ */
+tarval *tarval_sub(tarval *a, tarval *b, ir_mode *dst_mode);
-/** Multiplication of tarvals. */
+/**
+ * Multiplication of tarvals.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a * b or tarval_bad
+ */
tarval *tarval_mul(tarval *a, tarval *b);
-/** 'Exact' division of two tarvals. */
+/**
+ * Division of two floating point tarvals.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a / b or tarval_bad
+ */
tarval *tarval_quo(tarval *a, tarval *b);
-/** Integer division of two tarvals. */
+/**
+ * Integer division of two tarvals.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a / b or tarval_bad
+ */
tarval *tarval_div(tarval *a, tarval *b);
-/** Remainder of integer division. */
+/**
+ * Remainder of integer division.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a % b or tarval_bad
+ */
tarval *tarval_mod(tarval *a, tarval *b);
-/** Integer division AND remainder. */
+/**
+ * Integer division AND remainder.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ * @param mod_res after return, contains the remainder result, a % b or tarval_bad
+ *
+ * @return a / b or tarval_bad
+ */
tarval *tarval_divmod(tarval *a, tarval *b, tarval **mod_res);
-/** Absolute value of a tarval. */
+/**
+ * Absolute value of a tarval.
+ *
+ * @param a the first tarval
+ *
+ * @return |a| or tarval_bad
+ */
tarval *tarval_abs(tarval *a);
-/** Bitwise and. */
+/**
+ * Bitwise and of two integer tarvals.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a & b or tarval_bad
+ */
tarval *tarval_and(tarval *a, tarval *b);
-/** Bitwise or. */
+/**
+ * Bitwise or of two integer tarvals.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a | b or tarval_bad
+ */
tarval *tarval_or(tarval *a, tarval *b);
-/** Bitwise exclusive or. */
+/**
+ * Bitwise exclusive or of two integer tarvals.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a ^ b or tarval_bad
+ */
tarval *tarval_eor(tarval *a, tarval *b);
-/** Left shift. */
+/**
+ * Logical Left shift.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a << b or tarval_bad
+ */
tarval *tarval_shl(tarval *a, tarval *b);
-/** Unsigned (logical) right shift. */
+/**
+ * Unsigned (logical) right shift.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a >>u b or tarval_bad
+ */
tarval *tarval_shr(tarval *a, tarval *b);
-/** Signed (arithmetic) right shift. */
+/**
+ * Signed (arithmetic) right shift.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a >>s b or tarval_bad
+ */
tarval *tarval_shrs(tarval *a, tarval *b);
-/** Rotation to left. */
+/**
+ * Rotation to left.
+ *
+ * @param a the first tarval
+ * @param b the second tarval
+ *
+ * @return a <<L>> b or tarval_bad
+ */
tarval *tarval_rotl(tarval *a, tarval *b);
/**
return ir_no_alias;
}
/* tv_size > tv2, so we can subtract without overflow */
- tv2 = tarval_sub(tv_size, tv2);
+ tv2 = tarval_sub(tv_size, tv2, NULL);
/* tv1 is < 0, so we can negate it */
tv1 = tarval_neg(tv1);
tv2 = t;
}
/* tv1 is now the "smaller" one */
- tv = tarval_sub(tv2, tv1);
+ tv = tarval_sub(tv2, tv1, NULL);
tv_size = new_tarval_from_long(size, get_tarval_mode(tv));
return tarval_cmp(tv_size, tv) & (pn_Cmp_Eq|pn_Cmp_Lt) ? ir_no_alias : ir_may_alias;
}
#define SHL(a, b) tarval_shl(a, b)
#define SHR(a, b) tarval_shr(a, b)
#define ADD(a, b) tarval_add(a, b)
-#define SUB(a, b) tarval_sub(a, b)
+#define SUB(a, b) tarval_sub(a, b, NULL)
#define MUL(a, b) tarval_mul(a, b)
#define DIV(a, b) tarval_div(a, b)
#define MOD(a, b) tarval_mod(a, b)
tarval *ta = value_of(a);
tarval *tb = value_of(b);
- if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b)))
+ if ((ta != tarval_bad) && (tb != tarval_bad))
return tarval_add(ta, tb);
return tarval_bad;
* Special case: a - a
*/
static tarval *computed_value_Sub(ir_node *n) {
- ir_node *a = get_Sub_left(n);
- ir_node *b = get_Sub_right(n);
- tarval *ta;
- tarval *tb;
+ ir_mode *mode = get_irn_mode(n);
+ ir_node *a = get_Sub_left(n);
+ ir_node *b = get_Sub_right(n);
+ tarval *ta;
+ tarval *tb;
/* a - a */
if (a == b && !is_Bad(a))
- return get_mode_null(get_irn_mode(n));
+ return get_mode_null(mode);
ta = value_of(a);
tb = value_of(b);
- if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b)))
- return tarval_sub(ta, tb);
+ if ((ta != tarval_bad) && (tb != tarval_bad))
+ return tarval_sub(ta, tb, mode);
return tarval_bad;
} /* computed_value_Sub */
tarval *ta = value_of(a);
tarval *tb = value_of(b);
- /* This was missing in original implementation. Why? */
- if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
+ if ((ta != tarval_bad) && (tb != tarval_bad)) {
if (tb != get_mode_null(get_tarval_mode(tb))) /* div by zero: return tarval_bad */
return tarval_quo(ta, tb);
}
return 1;
} /* is_const_Phi */
+typedef tarval *(*tarval_sub_type)(tarval *a, tarval *b, ir_mode *mode);
+typedef tarval *(*tarval_binop_type)(tarval *a, tarval *b);
+
+/**
+ * Wrapper for the tarval binop evaluation, tarval_sub has one more parameter.
+ */
+static tarval *do_eval(tarval *(*eval)(), tarval *a, tarval *b, ir_mode *mode) {
+ if (eval == tarval_sub) {
+ tarval_sub_type func = (tarval_sub_type)eval;
+
+ return func(a, b, mode);
+ } else {
+ tarval_binop_type func = (tarval_binop_type)eval;
+
+ return func(a, b);
+ }
+}
+
/**
* Apply an evaluator on a binop with a constant operators (and one Phi).
*
*
* @return a new Phi node if the conversion was successful, NULL else
*/
-static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)(tarval *, tarval *), ir_mode *mode, int left) {
+static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)(), ir_mode *mode, int left) {
tarval *tv;
void **res;
ir_node *pred;
for (i = 0; i < n; ++i) {
pred = get_irn_n(phi, i);
tv = get_Const_tarval(pred);
- tv = eval(other, tv);
+ tv = do_eval(eval, other, tv, mode);
if (tv == tarval_bad) {
/* folding failed, bad */
for (i = 0; i < n; ++i) {
pred = get_irn_n(phi, i);
tv = get_Const_tarval(pred);
- tv = eval(tv, other);
+ tv = do_eval(eval, tv, other, mode);
if (tv == tarval_bad) {
/* folding failed, bad */
*
* @return a new Phi node if the conversion was successful, NULL else
*/
-static ir_node *apply_binop_on_2_phis(ir_node *a, ir_node *b, tarval *(*eval)(tarval *, tarval *), ir_mode *mode) {
+static ir_node *apply_binop_on_2_phis(ir_node *a, ir_node *b, tarval *(*eval)(), ir_mode *mode) {
tarval *tv_l, *tv_r, *tv;
void **res;
ir_node *pred;
tv_l = get_Const_tarval(pred);
pred = get_irn_n(b, i);
tv_r = get_Const_tarval(pred);
- tv = eval(tv_l, tv_r);
+ tv = do_eval(eval, tv_l, tv_r, mode);
if (tv == tarval_bad) {
/* folding failed, bad */
/* c > 0 : a < c ==> a <= (c-1) a >= c ==> a > (c-1) */
if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Ge) &&
tarval_cmp(tv, get_mode_null(mode)) == pn_Cmp_Gt) {
- tv = tarval_sub(tv, get_mode_one(mode));
+ tv = tarval_sub(tv, get_mode_one(mode), NULL);
if (tv != tarval_bad) {
proj_nr ^= pn_Cmp_Eq;
}
if (tv2 != tarval_bad) {
- tv2 = tarval_sub(tv, tv2);
+ tv2 = tarval_sub(tv, tv2, NULL);
if (tv2 != tarval_bad) {
left = a;
}
/* -a == c ==> a == -c, -a != c ==> a != -c */
else if (is_Minus(left)) {
- tarval *tv2 = tarval_sub(get_mode_null(mode), tv);
+ tarval *tv2 = tarval_sub(get_mode_null(mode), tv, NULL);
if (tv2 != tarval_bad) {
left = get_Minus_op(left);
tarval *cond = new_tarval_from_long(get_mode_size_bits(mode), get_tarval_mode(tv1));
ir_node *sl, *blk;
- cond = tarval_sub(cond, tv1);
+ cond = tarval_sub(cond, tv1, NULL);
cond = tarval_shrs(tv, cond);
if (!tarval_is_all_one(cond) && !tarval_is_null(cond)) {
ir_node *blk = get_irn_n(op, -1);
ir_mode *mode = get_irn_mode(v);
- tv = tarval_sub(tv, get_mode_one(mode));
+ tv = tarval_sub(tv, get_mode_one(mode), NULL);
left = new_rd_And(get_irn_dbg_info(op), current_ir_graph, blk, v, new_Const(mode, tv), mode);
changed |= 1;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_MOD_TO_AND);
pnc = tarval_cmp(tv_shl, tv_shr);
if (pnc == pn_Cmp_Lt || pnc == pn_Cmp_Eq) {
- tv_shift = tarval_sub(tv_shr, tv_shl);
+ tv_shift = tarval_sub(tv_shr, tv_shl, NULL);
new_const = new_Const(get_tarval_mode(tv_shift), tv_shift);
if (need_shrs) {
new_shift = new_rd_Shrs(dbgi, irg, block, x, new_const, mode);
}
} else {
assert(pnc == pn_Cmp_Gt);
- tv_shift = tarval_sub(tv_shl, tv_shr);
+ tv_shift = tarval_sub(tv_shl, tv_shr, NULL);
new_const = new_Const(get_tarval_mode(tv_shift), tv_shift);
new_shift = new_rd_Shl(dbgi, irg, block, x, new_const, mode);
}
tarval *diff, *min;
if (tarval_cmp(a, b) & pn_Cmp_Gt) {
- diff = tarval_sub(a, b);
+ diff = tarval_sub(a, b, NULL);
min = b;
} else {
- diff = tarval_sub(b, a);
+ diff = tarval_sub(b, a, NULL);
min = a;
}
conds[0] = sel;
- vals[0] = new_Const(mode, tarval_sub(a, min));
- vals[1] = new_Const(mode, tarval_sub(b, min));
+ vals[0] = new_Const(mode, tarval_sub(a, min, NULL));
+ vals[1] = new_Const(mode, tarval_sub(b, min, NULL));
n = new_rd_Psi(dbg, irg, block, 1, conds, vals, mode);
n = new_rd_Add(dbg, irg, block, n, new_Const(mode, min), mode);
return n;
(pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) {
/* x >=|>|!= lo || x ==|>=|> hi -> x ==|>=|> hi */
return proj_hi;
- } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo))) { /* lo + 1 == hi */
+ } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo, NULL))) { /* lo + 1 == hi */
if (pnc_lo == pn_Cmp_Ge && pnc_hi == pn_Cmp_Lt) {
/* x >= c || x < c + 1 -> x == c */
ir_graph *const irg = current_ir_graph;
(pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) {
/* x >=|>|!= lo || x ==|>=|> hi -> x >=|>|!= lo */
return proj_lo;
- } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo))) { /* lo + 1 == hi */
+ } else if (tarval_is_one(tarval_sub(tv_hi, tv_lo, NULL))) { /* lo + 1 == hi */
if (pnc_lo == pn_Cmp_Lt && pnc_hi == pn_Cmp_Ge) {
/* x < c || x >= c + 1 -> x != c */
ir_graph *const irg = current_ir_graph;
node->type.tv = tarval_top;
} else if (is_con(a) && is_con(b)) {
if (is_tarval(a.tv) && is_tarval(b.tv)) {
- node->type.tv = tarval_sub(a.tv, b.tv);
+ node->type.tv = tarval_sub(a.tv, b.tv, get_irn_mode(sub));
} else if (is_tarval(a.tv) && tarval_is_null(a.tv)) {
node->type = b;
} else if (is_tarval(b.tv) && tarval_is_null(b.tv)) {
DB((dbg, LEVEL_4, " + %+F", tv_r));
break;
case iro_Sub:
- tv = tarval_sub(tv_l, tv_r);
- tv_init = tarval_sub(tv_init, tv_r);
+ tv = tarval_sub(tv_l, tv_r, NULL);
+ tv_init = tarval_sub(tv_init, tv_r, NULL);
DB((dbg, LEVEL_4, " - %+F", tv_r));
break;
default:
tv = tarval_add(tv, tv_incr);
} else {
assert(pscc->code == iro_Sub);
- tv = tarval_sub(tv, tv_incr);
+ tv = tarval_sub(tv, tv_incr, NULL);
}
tarval_set_integer_overflow_mode(ovmode);
tarval *tarval_add(tarval *a, tarval *b) {
tarval *res;
char *buffer;
- ir_mode *dst_mode, *src_mode = NULL;
+ ir_mode *imm_mode, *dst_mode = NULL;
assert(a);
assert(b);
}
if (mode_is_reference(a->mode)) {
- src_mode = a->mode;
- dst_mode = find_unsigned_mode(a->mode);
+ dst_mode = a->mode;
+ imm_mode = find_unsigned_mode(a->mode);
- if (dst_mode == NULL)
+ if (imm_mode == NULL)
return tarval_bad;
- a = tarval_convert_to(a, dst_mode);
- b = tarval_convert_to(b, dst_mode);
+ a = tarval_convert_to(a, imm_mode);
+ b = tarval_convert_to(b, imm_mode);
}
if (mode_is_reference(b->mode)) {
- src_mode = b->mode;
- dst_mode = find_unsigned_mode(b->mode);
+ dst_mode = b->mode;
+ imm_mode = find_unsigned_mode(b->mode);
- if (dst_mode == 0)
+ if (imm_mode == 0)
return tarval_bad;
- a = tarval_convert_to(a, dst_mode);
- b = tarval_convert_to(b, dst_mode);
+ a = tarval_convert_to(a, imm_mode);
+ b = tarval_convert_to(b, imm_mode);
}
assert(a->mode == b->mode);
default:
return tarval_bad;
}
- if (src_mode != NULL)
- return tarval_convert_to(res, src_mode);
+ if (dst_mode != NULL)
+ return tarval_convert_to(res, dst_mode);
return res;
}
/*
* subtraction
*/
-tarval *tarval_sub(tarval *a, tarval *b) {
+tarval *tarval_sub(tarval *a, tarval *b, ir_mode *dst_mode) {
tarval *res;
char *buffer;
- ir_mode *dst_mode, *src_mode = NULL;
assert(a);
assert(b);
/* vector arithmetic not implemented yet */
return tarval_bad;
}
- if (mode_is_reference(a->mode)) {
- src_mode = a->mode;
- dst_mode = find_unsigned_mode(a->mode);
-
- if (dst_mode == NULL)
- return tarval_bad;
- a = tarval_convert_to(a, dst_mode);
- b = tarval_convert_to(b, dst_mode);
- }
- if (mode_is_reference(b->mode)) {
- src_mode = b->mode;
- dst_mode = find_unsigned_mode(b->mode);
-
- if (dst_mode == 0)
- return tarval_bad;
-
- a = tarval_convert_to(a, dst_mode);
- b = tarval_convert_to(b, dst_mode);
+ if (dst_mode != NULL) {
+ if (mode_is_reference(a->mode)) {
+ a = tarval_convert_to(a, dst_mode);
+ }
+ if (mode_is_reference(b->mode)) {
+ b = tarval_convert_to(b, dst_mode);
+ }
+ assert(a->mode == dst_mode);
}
-
assert(a->mode == b->mode);
switch (get_mode_sort(a->mode)) {
/* modes of a,b are equal, so result has mode of a as this might be the character */
buffer = alloca(sc_get_buffer_length());
sc_sub(a->value, b->value, buffer);
- res = get_tarval_overflow(buffer, a->length, a->mode);
- break;
+ return get_tarval_overflow(buffer, a->length, a->mode);
case irms_float_number:
if (no_float)
return tarval_bad;
fc_sub(a->value, b->value, NULL);
- res = get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
- break;
+ return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
default:
return tarval_bad;
}
- if (src_mode != NULL)
- return tarval_convert_to(res, src_mode);
- return res;
}
/*