X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firopt.c;h=4fc0169aa03e8ecfbbd4038809d7cbc981c15fbd;hb=203717b8dd44597fb10c126b33a28528a2432e9c;hp=d7896ae70ff40dd52f763161170a28b18c84e198;hpb=feaa27743191b2b50a6cefc5f6beb425e5787065;p=libfirm diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index d7896ae70..4fc0169aa 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -178,7 +178,7 @@ static tarval *computed_value_Minus(ir_node *n) { ir_node *a = get_Minus_op(n); tarval *ta = value_of(a); - if ((ta != tarval_bad) && mode_is_signed(get_irn_mode(a))) + if (ta != tarval_bad) return tarval_neg(ta); return tarval_bad; @@ -1159,7 +1159,6 @@ static ir_node *equivalent_node_And(ir_node *n) { static ir_node *equivalent_node_Conv(ir_node *n) { ir_node *oldn = n; ir_node *a = get_Conv_op(n); - ir_node *b; ir_mode *n_mode = get_irn_mode(n); ir_mode *a_mode = get_irn_mode(a); @@ -1189,18 +1188,15 @@ static ir_node *equivalent_node_Conv(ir_node *n) { n = a; DBG_OPT_ALGSIM0(oldn, n, FS_OPT_CONV); } else if (is_Conv(a)) { /* Conv(Conv(b)) */ - ir_mode *b_mode; - - b = get_Conv_op(a); - n_mode = get_irn_mode(n); - b_mode = get_irn_mode(b); + ir_node *b = get_Conv_op(a); + ir_mode *b_mode = get_irn_mode(b); if (n_mode == b_mode) { if (n_mode == mode_b) { n = b; /* Convb(Conv*(xxxb(...))) == xxxb(...) */ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV); } else if (mode_is_int(n_mode)) { - if (smaller_mode(b_mode, a_mode)){ + if (get_mode_size_bits(b_mode) <= get_mode_size_bits(a_mode)) { n = b; /* ConvS(ConvL(xxxS(...))) == xxxS(...) */ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV); } @@ -1699,7 +1695,7 @@ static ir_op_ops *firm_set_default_equivalent_node(ir_opcode code, ir_op_ops *op static int is_const_Phi(ir_node *n) { int i; - if (! is_Phi(n)) + if (! is_Phi(n) || get_irn_arity(n) == 0) return 0; for (i = get_irn_arity(n) - 1; i >= 0; --i) if (! is_Const(get_irn_n(n, i))) @@ -1760,6 +1756,50 @@ static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)( return new_r_Phi(irg, get_nodes_block(phi), n, (ir_node **)res, mode); } /* apply_binop_on_phi */ +/** + * Apply an evaluator on a binop with two constant Phi. + * + * @param a the left Phi node + * @param b the right Phi node + * @param eval an evaluator function + * @param mode the mode of the result, may be different from the mode of the Phi! + * + * @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) { + tarval *tv_l, *tv_r, *tv; + void **res; + ir_node *pred; + ir_graph *irg; + int i, n; + + if (get_nodes_block(a) != get_nodes_block(b)) + return NULL; + + n = get_irn_arity(a); + NEW_ARR_A(void *, res, n); + + for (i = 0; i < n; ++i) { + pred = get_irn_n(a, i); + tv_l = get_Const_tarval(pred); + pred = get_irn_n(b, i); + tv_r = get_Const_tarval(pred); + tv = eval(tv_l, tv_r); + + if (tv == tarval_bad) { + /* folding failed, bad */ + return NULL; + } + res[i] = tv; + } + irg = current_ir_graph; + for (i = 0; i < n; ++i) { + pred = get_irn_n(a, i); + res[i] = new_r_Const_type(irg, get_irg_start_block(irg), mode, res[i], get_Const_type(pred)); + } + return new_r_Phi(irg, get_nodes_block(a), n, (ir_node **)res, mode); +} /* apply_binop_on_2_phis */ + /** * Apply an evaluator on a unop with a constant operator (a Phi). * @@ -1905,6 +1945,10 @@ static ir_node *transform_node_AddSub(ir_node *n) { /* check for Op(Const, Phi) */ \ c = apply_binop_on_phi(b, get_Const_tarval(a), eval, mode, 1);\ } \ + else if (is_const_Phi(a) && is_const_Phi(b)) { \ + /* check for Op(Phi, Phi) */ \ + c = apply_binop_on_2_phis(a, b, eval, mode); \ + } \ if (c) { \ DBG_OPT_ALGSIM0(oldn, c, FS_OPT_CONST_PHI); \ return c; \ @@ -1983,74 +2027,6 @@ static ir_node *transform_node_Add(ir_node *n) { DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B); return n; } - if (! is_reassoc_running()) { - /* do NOT execute this code if reassociation is enabled, it does the inverse! */ - if (is_Mul(a)) { - ir_node *ma = get_Mul_left(a); - ir_node *mb = get_Mul_right(a); - - if (b == ma) { - ir_node *blk = get_irn_n(n, -1); - n = new_rd_Mul( - get_irn_dbg_info(n), current_ir_graph, blk, - ma, - new_rd_Add( - get_irn_dbg_info(n), current_ir_graph, blk, - mb, - new_r_Const_long(current_ir_graph, blk, mode, 1), - mode), - mode); - DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A); - return n; - } else if (b == mb) { - ir_node *blk = get_irn_n(n, -1); - n = new_rd_Mul( - get_irn_dbg_info(n), current_ir_graph, blk, - mb, - new_rd_Add( - get_irn_dbg_info(n), current_ir_graph, blk, - ma, - new_r_Const_long(current_ir_graph, blk, mode, 1), - mode), - mode); - DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A); - return n; - } - } - if (is_Mul(b)) { - ir_node *ma = get_Mul_left(b); - ir_node *mb = get_Mul_right(b); - - if (a == ma) { - ir_node *blk = get_irn_n(n, -1); - n = new_rd_Mul( - get_irn_dbg_info(n), current_ir_graph, blk, - ma, - new_rd_Add( - get_irn_dbg_info(n), current_ir_graph, blk, - mb, - new_r_Const_long(current_ir_graph, blk, mode, 1), - mode), - mode); - DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A); - return n; - } - if (a == mb) { - ir_node *blk = get_irn_n(n, -1); - n = new_rd_Mul( - get_irn_dbg_info(n), current_ir_graph, blk, - mb, - new_rd_Add( - get_irn_dbg_info(n), current_ir_graph, blk, - ma, - new_r_Const_long(current_ir_graph, blk, mode, 1), - mode), - mode); - DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A); - return n; - } - } - } if (get_mode_arithmetic(mode) == irma_twos_complement) { /* Here we rely on constants be on the RIGHT side */ if (is_Not(a)) { @@ -2267,16 +2243,16 @@ restart: if (mode == get_irn_mode(b)) { ir_mode *ma, *mb; - - a = get_Conv_op(a); - b = get_Conv_op(b); + ir_node *op_a = get_Conv_op(a); + ir_node *op_b = get_Conv_op(b); /* check if it's allowed to skip the conv */ - ma = get_irn_mode(a); - mb = get_irn_mode(b); + ma = get_irn_mode(op_a); + mb = get_irn_mode(op_b); if (mode_is_reference(ma) && mode_is_reference(mb)) { /* SubInt(ConvInt(aP), ConvInt(bP)) -> SubInt(aP,bP) */ + a = op_a; b = op_b; set_Sub_left(n, a); set_Sub_right(n, b); @@ -2510,10 +2486,39 @@ static ir_node *transform_node_Mul(ir_node *n) { * Transform a Div Node. */ static ir_node *transform_node_Div(ir_node *n) { - tarval *tv = value_of(n); ir_mode *mode = get_Div_resmode(n); - ir_node *value = n; + ir_node *a = get_Div_left(n); + ir_node *b = get_Div_right(n); + ir_node *value; + tarval *tv; + + if (is_Const(b) && is_const_Phi(a)) { + /* check for Div(Phi, Const) */ + value = apply_binop_on_phi(a, get_Const_tarval(b), tarval_div, mode, 0); + if (value) { + DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + else if (is_Const(a) && is_const_Phi(b)) { + /* check for Div(Const, Phi) */ + value = apply_binop_on_phi(b, get_Const_tarval(a), tarval_div, mode, 1); + if (value) { + DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + else if (is_const_Phi(a) && is_const_Phi(b)) { + /* check for Div(Phi, Phi) */ + value = apply_binop_on_2_phis(a, b, tarval_div, mode); + if (value) { + DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + value = n; + tv = value_of(n); if (tv != tarval_bad) { value = new_Const(get_tarval_mode(tv), tv); @@ -2569,10 +2574,39 @@ make_tuple: * Transform a Mod node. */ static ir_node *transform_node_Mod(ir_node *n) { - tarval *tv = value_of(n); ir_mode *mode = get_Mod_resmode(n); - ir_node *value = n; + ir_node *a = get_Mod_left(n); + ir_node *b = get_Mod_right(n); + ir_node *value; + tarval *tv; + + if (is_Const(b) && is_const_Phi(a)) { + /* check for Div(Phi, Const) */ + value = apply_binop_on_phi(a, get_Const_tarval(b), tarval_mod, mode, 0); + if (value) { + DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + else if (is_Const(a) && is_const_Phi(b)) { + /* check for Div(Const, Phi) */ + value = apply_binop_on_phi(b, get_Const_tarval(a), tarval_mod, mode, 1); + if (value) { + DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + else if (is_const_Phi(a) && is_const_Phi(b)) { + /* check for Div(Phi, Phi) */ + value = apply_binop_on_2_phis(a, b, tarval_mod, mode); + if (value) { + DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + value = n; + tv = value_of(n); if (tv != tarval_bad) { value = new_Const(get_tarval_mode(tv), tv); @@ -2632,14 +2666,48 @@ static ir_node *transform_node_DivMod(ir_node *n) { ir_node *a = get_DivMod_left(n); ir_node *b = get_DivMod_right(n); ir_mode *mode = get_DivMod_resmode(n); - tarval *ta = value_of(a); - tarval *tb = value_of(b); + tarval *ta, *tb; int evaluated = 0; + ir_node *va, *vb; + + if (is_Const(b) && is_const_Phi(a)) { + /* check for Div(Phi, Const) */ + va = apply_binop_on_phi(a, get_Const_tarval(b), tarval_div, mode, 0); + vb = apply_binop_on_phi(a, get_Const_tarval(b), tarval_mod, mode, 0); + if (va && vb) { + DBG_OPT_ALGSIM0(n, va, FS_OPT_CONST_PHI); + DBG_OPT_ALGSIM0(n, vb, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + else if (is_Const(a) && is_const_Phi(b)) { + /* check for Div(Const, Phi) */ + va = apply_binop_on_phi(b, get_Const_tarval(a), tarval_div, mode, 1); + vb = apply_binop_on_phi(b, get_Const_tarval(a), tarval_mod, mode, 1); + if (va && vb) { + DBG_OPT_ALGSIM0(n, va, FS_OPT_CONST_PHI); + DBG_OPT_ALGSIM0(n, vb, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + else if (is_const_Phi(a) && is_const_Phi(b)) { + /* check for Div(Phi, Phi) */ + va = apply_binop_on_2_phis(a, b, tarval_div, mode); + vb = apply_binop_on_2_phis(a, b, tarval_mod, mode); + if (va && vb) { + DBG_OPT_ALGSIM0(n, va, FS_OPT_CONST_PHI); + DBG_OPT_ALGSIM0(n, vb, FS_OPT_CONST_PHI); + goto make_tuple; + } + } + ta = value_of(a); + tb = value_of(b); if (tb != tarval_bad) { if (tb == get_mode_one(get_tarval_mode(tb))) { - b = new_Const(mode, get_mode_null(mode)); - DBG_OPT_CSTEVAL(n, b); + va = a; + vb = new_Const(mode, get_mode_null(mode)); + DBG_OPT_CSTEVAL(n, vb); goto make_tuple; } else if (ta != tarval_bad) { tarval *resa, *resb; @@ -2648,28 +2716,30 @@ static ir_node *transform_node_DivMod(ir_node *n) { Jmp for X result!? */ resb = tarval_mod(ta, tb); if (resb == tarval_bad) return n; /* Causes exception! */ - a = new_Const(mode, resa); - b = new_Const(mode, resb); - DBG_OPT_CSTEVAL(n, a); - DBG_OPT_CSTEVAL(n, b); + va = new_Const(mode, resa); + vb = new_Const(mode, resb); + DBG_OPT_CSTEVAL(n, va); + DBG_OPT_CSTEVAL(n, vb); goto make_tuple; } else if (mode_is_signed(mode) && tb == get_mode_minus_one(mode)) { - a = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, get_irn_n(n, -1), a, mode); - b = new_Const(mode, get_mode_null(mode)); - DBG_OPT_CSTEVAL(n, a); - DBG_OPT_CSTEVAL(n, b); + va = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, get_irn_n(n, -1), a, mode); + vb = new_Const(mode, get_mode_null(mode)); + DBG_OPT_CSTEVAL(n, va); + DBG_OPT_CSTEVAL(n, vb); goto make_tuple; } else { /* Try architecture dependent optimization */ - arch_dep_replace_divmod_by_const(&a, &b, n); - evaluated = a != NULL; + va = a; + vb = b; + arch_dep_replace_divmod_by_const(&va, &vb, n); + evaluated = va != NULL; } } else if (a == b) { if (value_not_zero(a, &dummy)) { /* a/a && a != 0 */ - a = new_Const(mode, get_mode_one(mode)); - b = new_Const(mode, get_mode_null(mode)); - DBG_OPT_CSTEVAL(n, a); - DBG_OPT_CSTEVAL(n, b); + va = new_Const(mode, get_mode_one(mode)); + vb = new_Const(mode, get_mode_null(mode)); + DBG_OPT_CSTEVAL(n, va); + DBG_OPT_CSTEVAL(n, vb); goto make_tuple; } else { /* BEWARE: it is NOT possible to optimize a/a to 1, as this may cause a exception */ @@ -2677,7 +2747,7 @@ static ir_node *transform_node_DivMod(ir_node *n) { } } else if (ta == get_mode_null(mode) && value_not_zero(b, &dummy)) { /* 0 / non-Const = 0 */ - b = a; + vb = va = a; goto make_tuple; } @@ -2695,8 +2765,8 @@ make_tuple: set_Tuple_pred(n, pn_DivMod_M, mem); set_Tuple_pred(n, pn_DivMod_X_regular, new_r_Jmp(current_ir_graph, blk)); set_Tuple_pred(n, pn_DivMod_X_except, new_Bad()); /* no exception */ - set_Tuple_pred(n, pn_DivMod_res_div, a); - set_Tuple_pred(n, pn_DivMod_res_mod, b); + set_Tuple_pred(n, pn_DivMod_res_div, va); + set_Tuple_pred(n, pn_DivMod_res_mod, vb); } return n; @@ -2867,7 +2937,8 @@ static ir_node *transform_bitwise_distributive(ir_node *n, ir_node *b_left = get_binop_left(b); ir_node *b_right = get_binop_right(b); ir_node *c = NULL; - ir_node *op1, *op2; + ir_node *op1 = NULL; + ir_node *op2 = NULL; if (is_op_commutative(op)) { if (a_left == b_left) { @@ -2911,6 +2982,7 @@ static ir_node *transform_bitwise_distributive(ir_node *n, set_irn_n(n, -1, blk); set_binop_left(n, new_n); set_binop_right(n, c); + add_identities(current_ir_graph->value_table, n); } DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_SHIFT_AND); @@ -3177,6 +3249,9 @@ static ir_node *transform_node_Not(ir_node *n) { * Optimize: * -(~x) = x + 1 * -(a-b) = b - a + * -(a >>u (size-1)) = a >>s (size-1) + * -(a >>s (size-1)) = a >>u (size-1) + * -(a * const) -> a * -const */ static ir_node *transform_node_Minus(ir_node *n) { ir_node *c, *oldn = n; @@ -3252,6 +3327,7 @@ static ir_node *transform_node_Minus(ir_node *n) { ir_graph *irg = current_ir_graph; ir_node *block = get_nodes_block(a); n = new_rd_Mul(dbg, irg, block, mul_l, cnst, mode); + DBG_OPT_ALGSIM2(oldn, a, n, FS_OPT_MINUS_MUL_C); return n; } } @@ -3476,27 +3552,63 @@ static ir_node *transform_node_Proj_Cond(ir_node *proj) { return proj; } /* transform_node_Proj_Cond */ +/** + * Create a 0 constant of given mode. + */ +static ir_node *create_zero_const(ir_mode *mode) { + tarval *tv = get_mode_null(mode); + ir_node *cnst = new_Const(mode, tv); + + return cnst; +} + +/* the order of the values is important! */ +typedef enum const_class { + const_const = 0, + const_like = 1, + const_other = 2 +} const_class; + +static const_class classify_const(const ir_node* n) +{ + if (is_Const(n)) return const_const; + if (is_irn_constlike(n)) return const_like; + return const_other; +} + +/** + * Determines whether r is more constlike or has a larger index (in that order) + * than l. + */ +static int operands_are_normalized(const ir_node *l, const ir_node *r) +{ + const const_class l_order = classify_const(l); + const const_class r_order = classify_const(r); + return + l_order > r_order || + (l_order == r_order && get_irn_idx(l) <= get_irn_idx(r)); +} + /** * Normalizes and optimizes Cmp nodes. */ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { - ir_node *n = get_Proj_pred(proj); - ir_node *left = get_Cmp_left(n); - ir_node *right = get_Cmp_right(n); - ir_node *c = NULL; - tarval *tv = NULL; - int changed = 0; - ir_mode *mode = NULL; - long proj_nr = get_Proj_proj(proj); - - /* we can evaluate this direct */ + ir_node *n = get_Proj_pred(proj); + ir_node *left = get_Cmp_left(n); + ir_node *right = get_Cmp_right(n); + tarval *tv = NULL; + int changed = 0; + ir_mode *mode = NULL; + long proj_nr = get_Proj_proj(proj); + + /* we can evaluate some cases directly */ switch (proj_nr) { case pn_Cmp_False: return new_Const(mode_b, get_tarval_b_false()); case pn_Cmp_True: return new_Const(mode_b, get_tarval_b_true()); case pn_Cmp_Leg: - if(!mode_is_float(get_irn_mode(left))) + if (!mode_is_float(get_irn_mode(left))) return new_Const(mode_b, get_tarval_b_true()); break; default: @@ -3518,9 +3630,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { ir_mode *mode_left = get_irn_mode(op_left); ir_mode *mode_right = get_irn_mode(op_right); - if (smaller_mode(mode_left, mode) && smaller_mode(mode_right, mode) - && mode_is_signed(mode) == mode_is_signed(mode_left) - && mode_is_signed(mode) == mode_is_signed(mode_right)) { + if (smaller_mode(mode_left, mode) && smaller_mode(mode_right, mode)) { ir_graph *irg = current_ir_graph; ir_node *block = get_nodes_block(n); @@ -3545,88 +3655,129 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { /* remove operation of both sides if possible */ if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) { - ir_opcode lop = get_irn_opcode(left); - - if (lop == get_irn_opcode(right)) { - ir_node *ll, *lr, *rl, *rr; - - /* same operation on both sides, try to remove */ - switch (lop) { - case iro_Not: - case iro_Minus: - /* ~a CMP ~b => a CMP b, -a CMP -b ==> a CMP b */ - left = get_unop_op(left); - right = get_unop_op(right); - changed |= 1; - DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); - break; - case iro_Add: - ll = get_Add_left(left); - lr = get_Add_right(left); - rl = get_Add_left(right); - rr = get_Add_right(right); - - if (ll == rl) { - /* X + a CMP X + b ==> a CMP b */ - left = lr; - right = rr; - changed |= 1; - DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); - } else if (ll == rr) { - /* X + a CMP b + X ==> a CMP b */ - left = lr; - right = rl; - changed |= 1; - DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); - } else if (lr == rl) { - /* a + X CMP X + b ==> a CMP b */ - left = ll; - right = rr; - changed |= 1; - DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); - } else if (lr == rr) { - /* a + X CMP b + X ==> a CMP b */ - left = ll; - right = rl; + /* + * The following operations are NOT safe for floating point operations, for instance + * 1.0 + inf == 2.0 + inf, =/=> x == y + */ + if (mode_is_int(get_irn_mode(left))) { + unsigned lop = get_irn_opcode(left); + + if (lop == get_irn_opcode(right)) { + ir_node *ll, *lr, *rl, *rr; + + /* same operation on both sides, try to remove */ + switch (lop) { + case iro_Not: + case iro_Minus: + /* ~a CMP ~b => a CMP b, -a CMP -b ==> a CMP b */ + left = get_unop_op(left); + right = get_unop_op(right); changed |= 1; DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + break; + case iro_Add: + ll = get_Add_left(left); + lr = get_Add_right(left); + rl = get_Add_left(right); + rr = get_Add_right(right); + + if (ll == rl) { + /* X + a CMP X + b ==> a CMP b */ + left = lr; + right = rr; + changed |= 1; + DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + } else if (ll == rr) { + /* X + a CMP b + X ==> a CMP b */ + left = lr; + right = rl; + changed |= 1; + DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + } else if (lr == rl) { + /* a + X CMP X + b ==> a CMP b */ + left = ll; + right = rr; + changed |= 1; + DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + } else if (lr == rr) { + /* a + X CMP b + X ==> a CMP b */ + left = ll; + right = rl; + changed |= 1; + DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + } + break; + case iro_Sub: + ll = get_Sub_left(left); + lr = get_Sub_right(left); + rl = get_Sub_left(right); + rr = get_Sub_right(right); + + if (ll == rl) { + /* X - a CMP X - b ==> a CMP b */ + left = lr; + right = rr; + changed |= 1; + DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + } else if (lr == rr) { + /* a - X CMP b - X ==> a CMP b */ + left = ll; + right = rl; + changed |= 1; + DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + } + break; + case iro_Rot: + if (get_Rot_right(left) == get_Rot_right(right)) { + /* a ROT X CMP b ROT X ==> a CMP b */ + left = get_Rot_left(left); + right = get_Rot_left(right); + changed |= 1; + DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); + } + break; + default: + break; } - break; - case iro_Sub: - ll = get_Sub_left(left); - lr = get_Sub_right(left); - rl = get_Sub_left(right); - rr = get_Sub_right(right); - - if (ll == rl) { - /* X - a CMP X - b ==> a CMP b */ - left = lr; - right = rr; - changed |= 1; - DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); - } else if (lr == rr) { - /* a - X CMP b - X ==> a CMP b */ - left = ll; - right = rl; + } + + /* X+A == A, A+X == A, A-X == A -> X == 0 */ + if (is_Add(left) || is_Sub(left)) { + ir_node *ll = get_binop_left(left); + ir_node *lr = get_binop_right(left); + + if (lr == right && is_Add(left)) { + ir_node *tmp = ll; + ll = lr; + lr = tmp; + } + if (ll == right) { + left = lr; + right = create_zero_const(get_irn_mode(left)); changed |= 1; DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); } - break; - case iro_Rot: - if (get_Rot_right(left) == get_Rot_right(right)) { - /* a ROT X CMP b ROT X */ - left = get_Rot_left(left); - right = get_Rot_left(right); + } + if (is_Add(right) || is_Sub(right)) { + ir_node *rl = get_binop_left(right); + ir_node *rr = get_binop_right(right); + + if (rr == left && is_Add(right)) { + ir_node *tmp = rl; + rl = rr; + rr = tmp; + } + if (rl == left) { + left = rr; + right = create_zero_const(get_irn_mode(left)); changed |= 1; DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); } - break; - default: - break; } - } - } + } /* mode_is_int(...) */ + } /* proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg */ + /* replace mode_b compares with ands/ors */ if (get_irn_mode(left) == mode_b) { ir_graph *irg = current_ir_graph; ir_node *block = get_nodes_block(n); @@ -3654,21 +3805,8 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { * First step: normalize the compare op * by placing the constant on the right side * or moving the lower address node to the left. - * We ignore the case that both are constants - * this case should be optimized away. */ - if (is_Const(right)) { - c = right; - } else if (is_irn_constlike(left)) { - c = left; - left = right; - right = c; - if(!is_Const(c)) - c = NULL; - - proj_nr = get_inversed_pnc(proj_nr); - changed |= 1; - } else if (get_irn_idx(left) > get_irn_idx(right)) { + if (!operands_are_normalized(left, right)) { ir_node *t = left; left = right; @@ -3684,9 +3822,9 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { * later and may help to normalize more compares. * Of course this is only possible for integer values. */ - if (c) { - mode = get_irn_mode(c); - tv = get_Const_tarval(c); + if (is_Const(right)) { + mode = get_irn_mode(right); + tv = get_Const_tarval(right); /* TODO extend to arbitrary constants */ if (is_Conv(left) && tarval_is_null(tv)) { @@ -4043,9 +4181,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { /* create a new compare */ n = new_rd_Cmp(get_irn_dbg_info(n), current_ir_graph, block, left, right); - - set_Proj_pred(proj, n); - set_Proj_proj(proj, proj_nr); + proj = new_rd_Proj(get_irn_dbg_info(proj), current_ir_graph, block, n, get_irn_mode(proj), proj_nr); } return proj; @@ -4532,6 +4668,12 @@ static ir_node *transform_node_Conv(ir_node *n) { return c; } } + + if (is_Unknown(a)) { /* Conv_A(Unknown_B) -> Unknown_A */ + ir_mode *mode = get_irn_mode(n); + return new_r_Unknown(current_ir_graph, mode); + } + return n; } /* transform_node_Conv */ @@ -4671,7 +4813,6 @@ static ir_node *transform_node_Mux(ir_node *n) { return n; } } - } } } @@ -5083,7 +5224,7 @@ void del_identities(pset *value_table) { } /* del_identities */ /** - * Normalize a node by putting constants (and operands with smaller + * Normalize a node by putting constants (and operands with larger * node index) on the right * * @param n The node to normalize @@ -5093,17 +5234,12 @@ static void normalize_node(ir_node *n) { if (is_op_commutative(get_irn_op(n))) { ir_node *l = get_binop_left(n); ir_node *r = get_binop_right(n); - int l_idx = get_irn_idx(l); - int r_idx = get_irn_idx(r); /* For commutative operators perform a OP b == b OP a but keep - constants on the RIGHT side. This helps greatly in some optimizations. - Moreover we use the idx number to make the form deterministic. */ - if (is_irn_constlike(l)) - l_idx = -l_idx; - if (is_irn_constlike(r)) - r_idx = -r_idx; - if (l_idx < r_idx) { + * constants on the RIGHT side. This helps greatly in some + * optimizations. Moreover we use the idx number to make the form + * deterministic. */ + if (!operands_are_normalized(l, r)) { set_binop_left(n, r); set_binop_right(n, l); }