From: Matthias Braun Date: Wed, 16 Feb 2011 15:39:24 +0000 (+0000) Subject: normalize some bittest constructs X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=822286302c8472f89a7e8492b11bd3a9c702c1fe;p=libfirm normalize some bittest constructs [r28381] --- diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index ef3ea36b7..6e1628799 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -1933,28 +1933,24 @@ static ir_node *get_flags_node(ir_node *node, int *pnc_out) ir_node *ra = get_And_right(l); if (is_Shl(la)) { ir_node *c = get_Shl_left(la); - if (is_Const_1(c) && (is_Const_0(r) || r == la)) { + if (is_Const_1(c) && is_Const_0(r)) { /* (1 << n) & ra) */ ir_node *n = get_Shl_right(la); flags = gen_bt(pred, ra, n); /* we must generate a Jc/Jnc jump */ pnc = pnc == pn_Cmp_Lg ? pn_Cmp_Lt : pn_Cmp_Ge; - if (r == la) - pnc ^= pn_Cmp_Leg; *pnc_out = ia32_pn_Cmp_unsigned | pnc; return flags; } } if (is_Shl(ra)) { ir_node *c = get_Shl_left(ra); - if (is_Const_1(c) && (is_Const_0(r) || r == ra)) { + if (is_Const_1(c) && is_Const_0(r)) { /* la & (1 << n)) */ ir_node *n = get_Shl_right(ra); flags = gen_bt(pred, la, n); /* we must generate a Jc/Jnc jump */ pnc = pnc == pn_Cmp_Lg ? pn_Cmp_Lt : pn_Cmp_Ge; - if (r == ra) - pnc ^= pn_Cmp_Leg; *pnc_out = ia32_pn_Cmp_unsigned | pnc; return flags; } diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index e5595a62c..be69b26bf 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -3847,6 +3847,29 @@ static ir_node *transform_node_Proj_Cond(ir_node *proj) return proj; } /* transform_node_Proj_Cond */ +/** + * return true if the operation returns a value with exactly 1 bit set + * or none set + */ +static bool is_single_bit(const ir_node *node) +{ + /* a first implementation, could be extended with vrp and others... */ + if (is_Shl(node)) { + ir_node *shl_l = get_Shl_left(node); + ir_mode *mode = get_irn_mode(node); + int modulo = get_mode_modulo_shift(mode); + /* this works if we shift a 1 and we have modulo shift */ + if (is_Const(shl_l) && is_Const_one(shl_l) + && 0 < modulo && modulo <= (int)get_mode_size_bits(mode)) { + return true; + } + } else if (is_Const(node)) { + ir_tarval *tv = get_Const_tarval(node); + return tarval_is_single_bit(tv); + } + return false; +} + /** * Create a 0 constant of given mode. */ @@ -3868,7 +3891,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) ir_node *right = get_Cmp_right(n); ir_tarval *tv = NULL; int changed = 0; - ir_mode *mode = NULL; + ir_mode *mode = get_irn_mode(left); long proj_nr = get_Proj_proj(proj); /* we can evaluate some cases directly */ @@ -3882,7 +3905,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) return new_r_Const(irg, get_tarval_b_true()); } case pn_Cmp_Leg: - if (!mode_is_float(get_irn_mode(left))) { + if (!mode_is_float(mode)) { ir_graph *irg = get_irn_irg(proj); return new_r_Const(irg, get_tarval_b_true()); } @@ -3898,7 +3921,6 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) /* Remove unnecessary conversions */ /* TODO handle constants */ if (is_Conv(left) && is_Conv(right)) { - ir_mode *mode = get_irn_mode(left); ir_node *op_left = get_Conv_op(left); ir_node *op_right = get_Conv_op(right); ir_mode *mode_left = get_irn_mode(op_left); @@ -3933,7 +3955,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) * 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))) { + if (mode_is_int(mode)) { unsigned lop = get_irn_opcode(left); if (lop == get_irn_opcode(right)) { @@ -4028,7 +4050,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) if (ll == right) { ir_graph *irg = get_irn_irg(n); left = lr; - right = create_zero_const(irg, get_irn_mode(left)); + right = create_zero_const(irg, mode); changed |= 1; DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); } @@ -4045,11 +4067,29 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) if (rl == left) { ir_graph *irg = get_irn_irg(n); left = rr; - right = create_zero_const(irg, get_irn_mode(left)); + right = create_zero_const(irg, mode); changed |= 1; DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP); } } + /* Cmp(And(1bit, val), 1bit) "bit-testing" can be replaced + * by the simpler Cmp(And(1bit), val), 0) negated pnc */ + if (is_And(left)) { + ir_node *and0 = get_And_left(left); + ir_node *and1 = get_And_right(left); + if (is_single_bit(and1)) { + ir_node *tmp = and0; + and0 = and1; + and1 = tmp; + } + if (and0 == right && is_single_bit(and0)) { + ir_graph *irg = get_irn_irg(n); + proj_nr = get_negated_pnc(proj_nr, mode); + right = create_zero_const(irg, mode); + changed |= 1; + } + } + if (is_And(left) && is_Const(right)) { ir_node *ll = get_binop_left(left); ir_node *lr = get_binop_right(left);