Commit 82228630 authored by Matthias Braun's avatar Matthias Braun
Browse files

normalize some bittest constructs

[r28381]
parent 96f04053
......@@ -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;
}
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment