Commit a169b4d8 authored by Michael Beck's avatar Michael Beck
Browse files

- tarval_sub() now has an additional parameter, needed for

  mode_ref - mode_ref = mode_int operations
- more doxygen docu added
- allow reference mode arithmetic

[r20888]
parent d8ed0076
......@@ -364,6 +364,8 @@ typedef enum _tarval_int_overflow_mode_t {
/**
* 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);
......@@ -442,55 +444,173 @@ tarval *tarval_convert_to(tarval *src, ir_mode *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);
/**
......
......@@ -181,7 +181,7 @@ static ir_alias_relation different_index(ir_node *idx1, ir_node *idx2, int size)
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);
......@@ -200,7 +200,7 @@ static ir_alias_relation different_index(ir_node *idx1, ir_node *idx2, int size)
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;
}
......
......@@ -634,7 +634,7 @@ static int tv_ld2(tarval *tv, int bits) {
#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)
......
......@@ -119,7 +119,7 @@ static tarval *computed_value_Add(ir_node *n) {
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;
......@@ -130,20 +130,21 @@ static tarval *computed_value_Add(ir_node *n) {
* 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 */
......@@ -243,8 +244,7 @@ static tarval *computed_value_Quot(ir_node *n) {
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);
}
......@@ -1798,6 +1798,24 @@ static int is_const_Phi(ir_node *n) {
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).
*
......@@ -1809,7 +1827,7 @@ static int is_const_Phi(ir_node *n) {
*
* @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;
......@@ -1821,7 +1839,7 @@ static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)(
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 */
......@@ -1833,7 +1851,7 @@ static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)(
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 */
......@@ -1861,7 +1879,7 @@ static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)(
*
* @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;
......@@ -1879,7 +1897,7 @@ static ir_node *apply_binop_on_2_phis(ir_node *a, ir_node *b, tarval *(*eval)(ta
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 */
......@@ -4047,7 +4065,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) {
/* 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;
......@@ -4115,7 +4133,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) {
}
if (tv2 != tarval_bad) {
tv2 = tarval_sub(tv, tv2);
tv2 = tarval_sub(tv, tv2, NULL);
if (tv2 != tarval_bad) {
left = a;
......@@ -4127,7 +4145,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) {
}
/* -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);
......@@ -4284,7 +4302,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) {
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)) {
......@@ -4326,7 +4344,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) {
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);
......@@ -4915,7 +4933,7 @@ static ir_node *transform_node_shl_shr(ir_node *n) {
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);
......@@ -4924,7 +4942,7 @@ static ir_node *transform_node_shl_shr(ir_node *n) {
}
} 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);
}
......@@ -5160,10 +5178,10 @@ static ir_node *transform_node_Mux(ir_node *n) {
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;
}
......@@ -5174,8 +5192,8 @@ static ir_node *transform_node_Mux(ir_node *n) {
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;
......
......@@ -100,7 +100,7 @@ static ir_node *bool_and(cond_pair* const cpair)
(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;
......@@ -161,7 +161,7 @@ static ir_node *bool_or(cond_pair *const cpair)
(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;
......
......@@ -1202,7 +1202,7 @@ static void compute_Sub(node_t *node) {
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)) {
......
......@@ -1112,8 +1112,8 @@ static ir_node *applyOneEdge(ir_node *iv, ir_node *rc, LFTR_edge *e, iv_env *env
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:
......@@ -1125,7 +1125,7 @@ static ir_node *applyOneEdge(ir_node *iv, ir_node *rc, LFTR_edge *e, iv_env *env
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);
......
......@@ -1101,7 +1101,7 @@ tarval *tarval_neg(tarval *a) {
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);
......@@ -1112,24 +1112,24 @@ tarval *tarval_add(tarval *a, tarval *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);
......@@ -1153,18 +1153,17 @@ tarval *tarval_add(tarval *a, tarval *b) {
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);
......@@ -1173,27 +1172,16 @@ tarval *tarval_sub(tarval *a, tarval *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)) {
......@@ -1201,23 +1189,18 @@ tarval *tarval_sub(tarval *a, tarval *b) {
/* 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;
}
/*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment