From: Michael Beck Date: Fri, 1 Aug 2008 10:26:43 +0000 (+0000) Subject: - tarval_sub() now has an additional parameter, needed for X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=a169b4d8ce0f7187ed45f9142f28fd0600588ded;p=libfirm - 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] --- diff --git a/include/libfirm/tv.h b/include/libfirm/tv.h index 870dc066e..a5ff79150 100644 --- a/include/libfirm/tv.h +++ b/include/libfirm/tv.h @@ -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 <> b or tarval_bad + */ tarval *tarval_rotl(tarval *a, tarval *b); /** diff --git a/ir/ana/irmemory.c b/ir/ana/irmemory.c index 0f7ee4844..c3f8503d9 100644 --- a/ir/ana/irmemory.c +++ b/ir/ana/irmemory.c @@ -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; } diff --git a/ir/ir/irarch.c b/ir/ir/irarch.c index 5f9fdfe96..549b747c5 100644 --- a/ir/ir/irarch.c +++ b/ir/ir/irarch.c @@ -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) diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 7603a490b..d997ac021 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -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; diff --git a/ir/opt/boolopt.c b/ir/opt/boolopt.c index ca97dc47b..6ff2a34c7 100644 --- a/ir/opt/boolopt.c +++ b/ir/opt/boolopt.c @@ -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; diff --git a/ir/opt/combo.c b/ir/opt/combo.c index 0c2b98166..96746bc1b 100644 --- a/ir/opt/combo.c +++ b/ir/opt/combo.c @@ -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)) { diff --git a/ir/opt/opt_osr.c b/ir/opt/opt_osr.c index 7144e18fe..b709a6ff0 100644 --- a/ir/opt/opt_osr.c +++ b/ir/opt/opt_osr.c @@ -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); diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 083e6303f..96fcc6eb8 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -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; } /*