X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firopt.c;h=c47d72a979359ef99da2a0f7bd16e0a291a72ba1;hb=77758e667d95420460ae94756f64a56171a518f3;hp=42ade93b26df15f2b57ec496d9627b8065ceb159;hpb=69bc79c78e8571f4ba51db0382977e196b18e561;p=libfirm diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 42ade93b2..c47d72a97 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -990,7 +990,7 @@ static ir_node *equivalent_node_idempotent_unop(ir_node *n) { /* optimize symmetric unop */ if (get_irn_op(pred) == get_irn_op(n)) { n = get_unop_op(pred); - DBG_OPT_ALGSIM2(oldn, pred, n); + DBG_OPT_ALGSIM2(oldn, pred, n, FS_OPT_IDEM_UNARY); } return n; } /* equivalent_node_idempotent_unop */ @@ -2364,15 +2364,123 @@ static ir_node *transform_node_Cond(ir_node *n) { return n; } /* transform_node_Cond */ +typedef ir_node* (*recursive_transform) (ir_node *n); + +/** + * makes use of distributive laws for and, or, eor + * and(a OP c, b OP c) -> and(a, b) OP c + */ +static ir_node *transform_bitwise_distributive(ir_node *n, + recursive_transform trans_func) +{ + ir_node *oldn = n; + ir_node *a = get_binop_left(n); + ir_node *b = get_binop_right(n); + ir_op *op = get_irn_op(a); + ir_op *op_root = get_irn_op(n); + + if(op != get_irn_op(b)) + return n; + + if (op == op_Conv) { + ir_node *a_op = get_Conv_op(a); + ir_node *b_op = get_Conv_op(b); + ir_mode *a_mode = get_irn_mode(a_op); + ir_mode *b_mode = get_irn_mode(b_op); + if(a_mode == b_mode && (mode_is_int(a_mode) || a_mode == mode_b)) { + ir_node *blk = get_irn_n(n, -1); + + n = exact_copy(n); + set_binop_left(n, a_op); + set_binop_right(n, b_op); + set_irn_mode(n, a_mode); + n = trans_func(n); + n = new_r_Conv(current_ir_graph, blk, n, get_irn_mode(oldn)); + + DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_SHIFT_AND); + return n; + } + } + + if (op == op_Eor) { + /* nothing to gain here */ + return n; + } + + if (op == op_Shrs || op == op_Shr || op == op_Shl + || op == op_And || op == op_Or || op == op_Eor) { + ir_node *a_left = get_binop_left(a); + ir_node *a_right = get_binop_right(a); + ir_node *b_left = get_binop_left(b); + ir_node *b_right = get_binop_right(b); + ir_node *c = NULL; + ir_node *op1, *op2; + + if (is_op_commutative(op)) { + if (a_left == b_left) { + c = a_left; + op1 = a_right; + op2 = b_right; + } else if(a_left == b_right) { + c = a_left; + op1 = a_right; + op2 = b_left; + } else if(a_right == b_left) { + c = a_right; + op1 = a_left; + op2 = b_right; + } + } + if(a_right == b_right) { + c = a_right; + op1 = a_left; + op2 = b_left; + } + + if (c != NULL) { + /* (a sop c) & (b sop c) => (a & b) sop c */ + ir_node *blk = get_irn_n(n, -1); + + ir_node *new_n = exact_copy(n); + set_binop_left(new_n, op1); + set_binop_right(new_n, op2); + new_n = trans_func(new_n); + + if(op_root == op_Eor && op == op_Or) { + dbg_info *dbgi = get_irn_dbg_info(n); + ir_graph *irg = current_ir_graph; + ir_mode *mode = get_irn_mode(c); + + c = new_rd_Not(dbgi, irg, blk, c, mode); + n = new_rd_And(dbgi, irg, blk, new_n, c, mode); + } else { + n = exact_copy(a); + set_irn_n(n, -1, blk); + set_binop_left(n, new_n); + set_binop_right(n, c); + } + + + DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_SHIFT_AND); + return n; + } + } + + return n; +} + /** * Transform an And. */ static ir_node *transform_node_And(ir_node *n) { - ir_node *c, *oldn = n; + ir_node *c, *oldn; ir_node *a = get_And_left(n); ir_node *b = get_And_right(n); HANDLE_BINOP_PHI(tarval_and, a,b,c); + + n = transform_bitwise_distributive(n, transform_node_And); + return n; } /* transform_node_And */ @@ -2409,6 +2517,8 @@ static ir_node *transform_node_Eor(ir_node *n) { n = new_r_Not(current_ir_graph, get_irn_n(n, -1), a, mode_b); DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT); + } else { + n = transform_bitwise_distributive(n, transform_node_Eor); } return n; @@ -2420,30 +2530,53 @@ static ir_node *transform_node_Eor(ir_node *n) { static ir_node *transform_node_Not(ir_node *n) { ir_node *c, *oldn = n; ir_node *a = get_Not_op(n); + ir_op *op_a = get_irn_op(a); HANDLE_UNOP_PHI(tarval_not,a,c); /* check for a boolean Not */ if ( (get_irn_mode(n) == mode_b) - && (get_irn_op(a) == op_Proj) + && (op_a == op_Proj) && (get_irn_mode(a) == mode_b) && (get_irn_op(get_Proj_pred(a)) == op_Cmp)) { /* We negate a Cmp. The Cmp has the negated result anyways! */ n = new_r_Proj(current_ir_graph, get_irn_n(n, -1), get_Proj_pred(a), mode_b, get_negated_pnc(get_Proj_proj(a), mode_b)); DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_CMP); + return n; + } + if (op_a == op_Sub && classify_Const(get_Sub_right(a)) == CNST_ONE) { + /* ~(x-1) = -x */ + ir_node *op = get_Sub_left(a); + ir_node *blk = get_irn_n(n, -1); + n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, blk, op, get_irn_mode(n)); + DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_MINUS_1); } return n; } /* transform_node_Not */ /** * Transform a Minus. + * Optimize: + * -(~x) = x + 1 */ static ir_node *transform_node_Minus(ir_node *n) { ir_node *c, *oldn = n; ir_node *a = get_Minus_op(n); HANDLE_UNOP_PHI(tarval_neg,a,c); + + if (is_Not(a)) { + /* -(~x) = x + 1 */ + ir_node *op = get_Not_op(a); + ir_mode *mode = get_irn_mode(op); + tarval *tv = get_mode_one(mode); + ir_node *blk = get_irn_n(n, -1); + ir_node *c = new_r_Const(current_ir_graph, blk, mode, tv); + n = new_rd_Add(get_irn_dbg_info(n), current_ir_graph, blk, op, c, mode); + DBG_OPT_ALGSIM2(oldn, a, n, FS_OPT_MINUS_NOT); + } + return n; } /* transform_node_Minus */ @@ -2702,10 +2835,12 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { (!mode_overflow_on_unary_Minus(mode) || (mode_is_int(mode) && (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg)))) { left = get_Minus_op(left); - tv = tarval_sub(get_mode_null(mode), tv); + tv = tarval_neg(tv); - proj_nr = get_inversed_pnc(proj_nr); - changed |= 2; + if (tv != tarval_bad) { + proj_nr = get_inversed_pnc(proj_nr); + changed |= 2; + } } /* for integer modes, we have more */ @@ -2722,16 +2857,20 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { tarval_cmp(tv, get_mode_null(mode)) == pn_Cmp_Gt) { tv = tarval_sub(tv, get_mode_one(mode)); - proj_nr ^= pn_Cmp_Eq; - changed |= 2; + if (tv != tarval_bad) { + proj_nr ^= pn_Cmp_Eq; + changed |= 2; + } } /* c < 0 : a > c ==> a >= (c+1) a <= c ==> a < (c+1) */ else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Le) && tarval_cmp(tv, get_mode_null(mode)) == pn_Cmp_Lt) { tv = tarval_add(tv, get_mode_one(mode)); - proj_nr ^= pn_Cmp_Eq; - changed |= 2; + if (tv != tarval_bad) { + proj_nr ^= pn_Cmp_Eq; + changed |= 2; + } } /* the following reassociations work only for == and != */ @@ -2743,7 +2882,9 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { left = get_Sub_left(left); tv = value_of(right); - changed = 1; + if (tv != tarval_bad) { + changed = 1; + } } if (tv != tarval_bad) { @@ -3150,6 +3291,10 @@ static ir_node *transform_node_Or(ir_node *n) { n = transform_node_Or_bf_store(n); n = transform_node_Or_Rot(n); + if (n != oldn) + return n; + + n = transform_bitwise_distributive(n, transform_node_Or); return n; } /* transform_node_Or */