X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firopt.c;h=94c3bfdaa64e25f71f590f50e161926530381cff;hb=fc5f7e1fbd10124c19b2583d74ab9472bfb95ebf;hp=724a6346de46f184cbb3c274efb2a86f8c8f1163;hpb=969f52a3743dd60803f8fd5122aa8c714d17ae32;p=libfirm diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 724a6346d..94c3bfdaa 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -2283,21 +2283,22 @@ restart: return n; } } - if (is_Sub(a)) { - ir_node *x = get_Sub_left(a); - ir_node *y = get_Sub_right(a); - ir_node *blk = get_irn_n(n, -1); - ir_mode *m_b = get_irn_mode(b); - ir_mode *m_y = get_irn_mode(y); + if (is_Sub(a)) { /* (x - y) - b -> x - (y + b) */ + ir_node *x = get_Sub_left(a); + ir_node *y = get_Sub_right(a); + ir_node *blk = get_irn_n(n, -1); + ir_mode *m_b = get_irn_mode(b); + ir_mode *m_y = get_irn_mode(y); + ir_mode *add_mode; ir_node *add; /* Determine the right mode for the Add. */ if (m_b == m_y) - mode = m_b; + add_mode = m_b; else if (mode_is_reference(m_b)) - mode = m_b; + add_mode = m_b; else if (mode_is_reference(m_y)) - mode = m_y; + add_mode = m_y; else { /* * Both modes are different but none is reference, @@ -2308,7 +2309,7 @@ restart: return n; } - add = new_r_Add(current_ir_graph, blk, y, b, mode); + add = new_r_Add(current_ir_graph, blk, y, b, add_mode); n = new_rd_Sub(get_irn_dbg_info(n), current_ir_graph, blk, x, add, mode); DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_SUB_X_Y_Z); @@ -3055,7 +3056,14 @@ static ir_node *transform_node_Eor(ir_node *n) { DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT_BOOL); } else if (is_Const(b)) { if (is_Not(a)) { /* ~x ^ const -> x ^ ~const */ - n = new_Const(mode, tarval_not(get_Const_tarval(b))); + ir_node *cnst = new_Const(mode, tarval_not(get_Const_tarval(b))); + ir_node *not_op = get_Not_op(a); + dbg_info *dbg = get_irn_dbg_info(n); + ir_graph *irg = current_ir_graph; + ir_node *block = get_nodes_block(n); + ir_mode *mode = get_irn_mode(n); + n = new_rd_Eor(dbg, irg, block, not_op, cnst, mode); + return n; } else if (is_Const_all_one(b)) { /* x ^ 1...1 -> ~1 */ n = new_r_Not(current_ir_graph, get_nodes_block(n), a, mode); DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT); @@ -3090,7 +3098,13 @@ static ir_node *transform_node_Not(ir_node *n) { if (is_Eor(a)) { ir_node *eor_b = get_Eor_right(a); if (is_Const(eor_b)) { /* ~(x ^ const) -> x ^ ~const */ - n = new_Const(mode, tarval_not(get_Const_tarval(eor_b))); + ir_node *cnst = new_Const(mode, tarval_not(get_Const_tarval(eor_b))); + ir_node *eor_a = get_Eor_left(a); + dbg_info *dbg = get_irn_dbg_info(n); + ir_graph *irg = current_ir_graph; + ir_node *block = get_nodes_block(n); + ir_mode *mode = get_irn_mode(n); + n = new_rd_Eor(dbg, irg, block, eor_a, cnst, mode); return n; } } @@ -3186,6 +3200,20 @@ static ir_node *transform_node_Minus(ir_node *n) { return n; } + if (is_Mul(a)) { /* -(a * const) -> a * -const */ + ir_node *mul_l = get_Mul_left(a); + ir_node *mul_r = get_Mul_right(a); + if (is_Const(mul_r)) { + tarval *tv = tarval_neg(get_Const_tarval(mul_r)); + ir_node *cnst = new_Const(mode, tv); + dbg_info *dbg = get_irn_dbg_info(a); + ir_graph *irg = current_ir_graph; + ir_node *block = get_nodes_block(a); + n = new_rd_Mul(dbg, irg, block, mul_l, cnst, mode); + return n; + } + } + return n; } /* transform_node_Minus */ @@ -3650,7 +3678,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { /* a-b == 0 ==> a == b, a-b != 0 ==> a != b */ if (tarval_is_null(tv) && is_Sub(left)) { - right =get_Sub_right(left); + right = get_Sub_right(left); left = get_Sub_left(left); tv = value_of(right); @@ -3746,12 +3774,36 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) { } /* tarval != bad */ } + if (changed & 2) /* need a new Const */ + right = new_Const(mode, tv); + + if ((proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) && is_Const(right) && is_Const_null(right) && is_Proj(left)) { + ir_node *op = get_Proj_pred(left); + + if ((is_Mod(op) && get_Proj_proj(left) == pn_Mod_res) || + (is_DivMod(op) && get_Proj_proj(left) == pn_DivMod_res_mod)) { + ir_node *c = get_binop_right(op); + + if (is_Const(c)) { + tarval *tv = get_Const_tarval(c); + + if (tarval_is_single_bit(tv)) { + /* special case: (x % 2^n) CMP 0 ==> x & (2^n-1) CMP 0 */ + ir_node *v = get_binop_left(op); + ir_node *blk = get_irn_n(op, -1); + ir_mode *mode = get_irn_mode(v); + + tv = tarval_sub(tv, get_mode_one(mode)); + left = new_rd_And(get_irn_dbg_info(op), current_ir_graph, blk, v, new_Const(mode, tv), mode); + changed |= 1; + } + } + } + } + if (changed) { ir_node *block = get_irn_n(n, -1); /* Beware of get_nodes_Block() */ - if (changed & 2) /* need a new Const */ - right = new_Const(mode, tv); - /* create a new compare */ n = new_rd_Cmp(get_irn_dbg_info(n), current_ir_graph, block, left, right);